npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

multiworker

v1.0.3

Published

Wrapper to make web workers easy.

Downloads

16

Readme

Summary

MultiWorker is a wrapper around node's and the browser's native (web) worker API. Features include:

  • Post data to workers and use callbacks to handle results.
  • Queue processes across multiple worker threads.
  • Build workers from functions, instead of needing a separate JS file.

Installation

Install via NPM:

npm install --save multiworker

Then use in your script:

import MultiWorker from 'multiworker';

Or, include the script the old fashioned way to make the MultiWorker constructor available globally:

<script src="dist/multiworker.min.js"></script>

Usage

Basic usage

A MultiWorker instance is created with a function which is used as the code for the worker.

var worker = new MultiWorker(function () {
  self.receive = function (n) {
    self.return(n + 1);
  }
});

In order to interact with the worker, we use the post method. This triggers the self.receive function inside the worker, which returns a value with self.return.

worker.post(5, function (n) {
  console.log(n); // => 6
});

Both worker.post() in the main thread and self.return() and self.post() in the worker can receive an array of transfers as last argument, to support Transferables.

var worker = new MultiWorker(function () {
  self.receive = function (inputBuffer) {
    // Worker now has ownership of the input buffer
    var resultBuffer = inputBuffer
    self.return(resultBuffer, [resultBuffer]);
    // Ownership of the result buffer has been transferred to the main thread
  }
});
var inputBuffer = new ArrayBuffer(5);
worker.post(inputBuffer, function(resultBuffer) {
  // Main thread now has ownership of the result buffer
}, [inputBuffer]);
// Ownership of the input buffer has been transferred to the worker

Options

worker

When creating a MultiWorker instance, a function can be passed:

var worker = new MultiWorker(function () {
  self.receive = self.return; // Simply return the input
});

Alternatively, a filepath, URL, or a stringified IIFE can be used.

var worker = new MultiWorker('workers/example.js');

worker.post('foo', function () {
  // This post won't occur until example.js has been fetched and the worker ready.
});

The worker can also be defined in an options object:

var worker = new MultiWorker({
  worker: function () {
    self.receive = self.return; // Simply return the input
  }
});

The worker url can also be passed as first argument, and all other options in an object literal as second argument:

var worker = new MultiWorker('workers/example.js', { threads: 2 })

callback

A function to be called whenever a worker sends a value back to the main program via self.post or self.return.

var worker = new MultiWorker({
  worker:   function () {
    self.receive = self.return; // Simply return the input
  },
  callback: function (val) {
    console.log(val);
  }
});

worker.post(1); // The callback function above will log 1 in the console

If a callback is passed as an argument when the post request is made, then the default callback is not used.

var worker = new MultiWorker({
  worker:   function () {
    self.receive = self.return; // Simply return the input
  },
  callback: function (val) {
    console.log(val);
  }
});

worker.post(1, function (val) {
  alert(val); // The callback function above will not be used. 1 will be alerted.
});

threads

The number of workers to spawn. The default is 1.

Multiple web workers:

var worker = new MultiWorker({
  worker:  function () {
    self.receive = self.return; // Simply return the input
  },
  threads: 2
});

// The posts below are processed in parallel.
// There is a chance that the second post will return first.
worker
  .post(42)
  .post(11);

A single web worker:

var worker = new MultiWorker({
  worker:  function () {
    self.receive = self.return; // Simply return the input
  },
  threads: 1
});

// The posts below are processed in series.
worker
  .post(42)
  .post(11);

dependencies

An array of named functions that can be used globally in the workers. These functions must be named and not make references to data outside the function scope.

var worker = new MultiWorker({
  worker: function () {
    self.receive = function (n1, n2) {
        self.return(multiply(n1, n2) + add(n1, n2));
    }
  },
    dependencies: [
      function multiply(n1, n2) {
        return n1 * n2;
      },
      function add(n1, n2) {
        return n1 + n2;
      }
  ]
});

worker.post(10, 2, function (n) {
  console.log(n); // => 32
});

MultiWorker Methods

post([...args], [callback], [transfers])

Interact with a MultiWorker instance. This method accepts an arbitrary number of parameters, which the worker can access with the self.receive method.

A callback can be passed - this is used instead of any default callback that may have been defined when creating the worker instance.

var worker = new MultiWorker(function () {
  self.receive = function (n1, n2) {
    self.return(n1 + n2);
  }
});

worker.post(2, 2, function (result) {
  console.log(result); // => 4
});

terminate([callback | instant])

Terminates the MultiWorker instance. The instance can no longer be used once this method has been called.

// Wait for post to return, then terminate
worker.post(10).terminate();
// Wait for post to return, then terminate and run the callback
worker.post(10).terminate(function () {
  console.log('Worker terminated');
});
// Terminate instantly, without waiting for result from any pending posts
worker.post(10).terminate(true);

Worker Methods

A few methods are made available inside the workers. These are attached to the self object.

self.receive([...args])

Fired in response to calling post() on a MultiWorker instance. This is the start of any process from within a worker.

var worker = new MultiWorker(function () {
  self.receive = function (n1, n2) {
    self.return(n1 + n2);
  }
});

worker.post(2, 2, function (result) {
  console.log(result); // => 4
});

self.return([...args], [transfers])

Sends a response back to the main thread. This will be called inside of self.receive - see the code example for that method for usage.

self.post([...args], [transfers])

Similar to self.return, but will not mark the current task as finished. self.return must be called after all work is done in order to start processing the next item in the queue.

var worker = new MultiWorker({
  worker:   function () {
    self.receive = function () {
      var i = 100;

      // A pointless loop to demonstrate.
      // A real-world usage could be a progress bar.
      while (i--) {
        if (i) {
          self.post(i);
        } else {
          self.return(i);
        }
      }
    }
  },
  callback: function (n) {
    if (!this.done) {
      console.log('left to complete: ' + n);
    } else {
      console.log('Finished');
    }
  }
});


worker
  .post()
  .post(); // This second post won't execute until self.return is called in response to the previous post.

Developing

To continuously run the tests while editing, run

npm start

and open your browser on http://localhost:3000.

To build the standalone version, run

npm run build

To ensure correct code style and that the library runs both in node and browsers, run

npm test

License

This project is licensed under the ISC License - see the LICENSE.md file for details