Skip to content

ogus/worker-thread

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Worker Thread

A tiny and flexible browser module that enables client-side multi-threading, based on inline WebWorkers

Table of Contents

Description

This module provides multi-threading in a browser context, by using Web Worker without an external file.

It uses the Blob API to build an object from an input function, convert it to a URL string, and instantiate an inline WebWorker from that URL. The WebWorker is then executed in a separate thread, whenever it is called through its messaging interface.

It is recommended to know how to use Web Workers before using this module, as the workflow and methods of the WorkerThread are based on the Web Worker API.

Features

  • Tiny module (~1.2kB)
  • Easy to use API, with various thread constructors
  • Flexible function execution (regular function, object's method, lambda function, etc.)
  • ES5 features only, for more browser compatibility
  • Easily readable code so you can build your own version !

Compatibility

IE Edge Firefox Chrome Safari Opera Mobile
10+ 13+ 23+ 6.1+ 15+

You can find the browser support for the Worker and Blob API on Can I Use: Web Workers, Blob Constructor, Blob URL. You can also find an overview of the compatibility on I Want To Use.

Install

You can import the module from Github with jsDelivr

<script src="https://cdn.jsdelivr.net/gh/ogus/worker-thread/worker-thread.min.js"></script>

You can clone the repository & include the worker-thread.js file in your project:

git clone https://github.com/ogus/worker-thread.git

Usage

The creation of a new thread is equivalent to the creation of a new Worker. The Worker does not need an external file to be instantiated, and it will execute the code in a new context.

// declare a Worker as if it was in a separate file
function threadConstructor = function (name) {
  self.name = name;
  self.value = 0;
  self.onmessage = function (e) {
    self.value += e.data;
    postMessage(self.name + ", value = " + self.value);
  }
}

// instantiate a new thread
var thread = WorkerThread.new(threadConstructor, "MyWorker");
// create a method to output the thread's messages
thread.onmessage = function (e) {
  console.log("thread message:", e.data);
}
// send messages to the thread
thread.postMessage(1);
thread.postMessage(10);

If your thread does not need to save data, you can just define the thread onmessage behavior

// create a Worker by defining its local message listener
var thread = WorkerThread.await(function (message) {
  var name = message.data;
  return "Hello " + name;
});

// create a message listener in the main thread
thread.onmessage = function (message) {
  console.log("New Worker message:", message.data);
}

// send messages !
thread.postMessage("World");
thread.postMessage("Bob");

Finally, if you just need to run a function without blocking the main thread, there is an even simpler way

WorkerThread.run(function (a, b) {
  return a + b;
}, 1, 2)
.then(function (e) {
  console.log(e.data);
});

API

A single static WorkerThread class is provided to instantiate and execute any type of thread.

WorkerThread.new(func, args=undefined)

Create a new WebWorker that can be used as a separated thread.

Input

  • func : The function used as a WebWorker constructor
  • args : The input arguments passed to the function

Notes

The input function should be a valid WebWorker constructor. It uses the self indentifier insteand of this, and it has access to a onmessage event listener and a postMessage method.

Any type and number of arguments can be used along with the input function: boolean, number, string, object, function...

var f = () => {};
WorkerThread.new(f, true, 3, ["a", "b", "c"], {left: true, right: false});

The Worker is using a separate context context: any variable declared outside the constructor is not accessible by the thread, and any worker variable is not accessible from the main thread.

Examples

var worker = WorkerThread.new(function () {
  self.count = 0;
  onmessage = function (message) {
    var n = message.data;
    self.count += n;
    postMessage("Current value: " + self.count);
  }
});

worker.onmessage = function (message) {
  var text = message.data;
  console.log(text);
};

worker.postMessage(1);
worker.postMessage(3);
worker.postMessage(-2);
function init(name) {
  var myName = name;

  function welcome(string) {
    return "Hello " + string + ", my name is " + myName;
  }

  onmessage = function (e) {
    var text = e.data;
    var response = welcome(text);
    postMessage(response);
  }
}

var workerBob = WorkerThread.new(init, "Bob");
workerBob.onmessage = (e) => { console.log(e.data); }

var workerJack = WorkerThread.new(init, "Jack");
workerJack.onmessage = (e) => { console.log(e.data); }

workerFoo.postMessage("Main");
workerBar.postMessage("Main");

WorkerThread.await(func, args=undefined)

Create a new Worker, with the input function used as its onmessage event listener. This is a shorthand to create a thread that only respond to incoming messages, without external behavior.

Input

  • func : The function used inside the message event listener
  • args : The input arguments passed to the function

Notes

The input function is wrapped in the internal onmessage event listener of the Worker.

The message object associated with this event is automaticaly passed to the input function as its first argument, and the return value of the input function is automaticaly sent with the postMessage method.

Examples

var thread = WorkerThread.await(function (message) {
  var array = message.data;
  return array.length;
});

wkThread.onmessage = (e) => console.log(e.data);

wkThread.postMessage([0, 1, 2]);  // output: 3
wkThread.postMessage(["A"]);  // output: 1

WorkerThread.run(func, args=undefined)

Create a new Worker that immediatly execute the input function and send back the result. This is the most simple way to instanciate a basic thread.

Input

  • func : Any function
  • args : Any arguments, passed to the input function

It return an object containing a then(func) method that accept any callback. This behavior is similar to Promise, while still being compatible with older browser.

Examples:

function ok() {
  return "Ok";
}

WorkerThread.run(ok).then(msg => {
  console.log(msg.data);  // output: 'ok'
});
function contains(array, value, message) {
  var index = array.indexOf(value);
  if (index > -1) {
    return index;
  }
  return message;
}

WorkerThread.run(contains, [1, 2, 3], 10, "nope").then(function (e) {
  console.log(e.data);  // output: 'nope'
});

Contributing

If you find a bug, a typo, or a missing feature, do not hesitate to contribute to this repository !

License

This project is licensed under the MIT License - see LICENSE for more details

About

A tiny and flexible browser module to create local threads, based on inline WebWorkers

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published