promise-worker
    TypeScript icon, indicating that this package has built-in type declarations

    2.0.1 • Public • Published

    promise-worker Build Status Coverage Status

    A small and performant library for communicating with Web Workers or Service Workers, using Promises. Post a message to the worker, get a message back.

    Goals:

    • Tiny footprint (~700 bytes min+gz)
    • Assumes you have a separate worker.js file (easier to debug, better browser support)

    Live examples:

    Usage

    Install:

    npm install promise-worker
    

    Inside your main bundle:

    // main.js
    var PromiseWorker = require('promise-worker');
    var worker = new Worker('worker.js');
    var promiseWorker = new PromiseWorker(worker);
     
    promiseWorker.postMessage('ping').then(function (response) {
      // handle response
    }).catch(function (error) {
      // handle error
    });

    Inside your worker.js bundle:

    // worker.js
    var registerPromiseWorker = require('promise-worker/register');
     
    registerPromiseWorker(function (message) {
      return 'pong';
    });

    Note that you require() two separate APIs, so the library is split between the worker.js and main file. This keeps the total bundle size smaller.

    If you prefer script tags, you can get PromiseWorker via:

    <script src="https://unpkg.com/promise-worker/dist/promise-worker.js"></script>

    And inside the worker, you can get registerPromiseWorker via:

    importScripts('https://unpkg.com/promise-worker/dist/promise-worker.register.js');

    Message format

    The message you send can be any object, array, string, number, etc.:

    // main.js
    promiseWorker.postMessage({
      hello: 'world',
      answer: 42,
      "this is fun": true
    }).then(/* ... */);
    // worker.js
    registerPromiseWorker(function (message) {
      console.log(message); // { hello: 'world', answer: 42, 'this is fun': true }
    });

    Note that the message will be JSON.stringifyd, so you can't send functions, Dates, custom classes, etc.

    Promises

    Inside of the worker, the registered handler can return either a Promise or a normal value:

    // worker.js
    registerPromiseWorker(function () {
      return Promise.resolve().then(function () {
        return 'much async, very promise';
      });
    });
    // main.js
    promiseWorker.postMessage(null).then(function (message) {
      console.log(message): // 'much async, very promise'
    });

    Ultimately, the value that is sent from the worker to the main thread is also stringifyd, so the same format rules apply.

    Error handling

    Any thrown errors or asynchronous rejections from the worker will be propagated to the main thread as a rejected Promise. For instance:

    // worker.js
    registerPromiseWorker(function (message) {
      throw new Error('naughty!');
    });
    // main.js
    promiseWorker.postMessage('whoops').catch(function (err) {
      console.log(err.message); // 'naughty!'
    });

    Note that stacktraces cannot be sent from the worker to the main thread, so you will have to debug those errors yourself. This library does however, print messages to console.error(), so you should see them there.

    Multi-type messages

    If you need to send messages of multiple types to the worker, just add some type information to the message you send:

    // main.js
    promiseWorker.postMessage({
      type: 'en'
    }).then(/* ... */);
     
    promiseWorker.postMessage({
      type: 'fr'
    }).then(/* ... */);
    // worker.js
    registerPromiseWorker(function (message) {
      if (message.type === 'en') {
        return 'Hello!';
      } else if (message.type === 'fr') {
        return 'Bonjour!';
      }
    });

    Service Workers

    Communicating with a Service Worker is the same as with a Web Worker. However, you have to wait for the Service Worker to install and start controlling the page. Here's an example:

    navigator.serviceWorker.register('sw.js', {
      scope: './'
    }).then(function () {
      if (navigator.serviceWorker.controller) {
        // already active and controlling this page
        return navigator.serviceWorker;
      }
      // wait for a new service worker to control this page
      return new Promise(function (resolve) {
        function onControllerChange() {
          navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
          resolve(navigator.serviceWorker);
        }
        navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
      });
    }).then(function (worker) { // the worker is ready
      var promiseWorker = new PromiseWorker(worker);
      return promiseWorker.postMessage('hello worker!');
    }).catch(console.log.bind(console));

    Then inside your Service Worker:

    var registerPromiseWorker = require('../register');
     
    registerPromiseWorker(function (msg) {
      return 'hello main thread!';
    });
     
    self.addEventListener('activate', function(event) {
      event.waitUntil(self.clients.claim()); // activate right now
    });

    Browser support

    Note that as of v2.0.0, promise-worker does not contain a built-in Promise polyfill. Use something like es6-promise if you need to support browsers that don't support Promises.

    See .zuul.yml for the full list of tested browsers. Assuming you have a Promise polyfill, the supported browsers should be:

    • Chrome
    • Firefox
    • Safari 8+
    • IE 10+
    • Edge
    • iOS 8+
    • Android 4.4+

    If a browser doesn't support Web Workers but you still want to use this library, then you can use pseudo-worker.

    For Service Worker support, Chrome 40 and 41 are known to be buggy (see #9), but 42+ are supported.

    This library is not designed to run in Node.js.

    API

    Main bundle

    new PromiseWorker(worker)

    Create a new PromiseWorker, using the given worker.

    PromiseWorker.postMessage(message)

    Send a message to the worker and return a Promise.

    • message - object - required
      • The message to send.
    • returns a Promise

    Worker bundle

    Register a message handler inside of the worker. Your handler consumes a message and returns a Promise or value.

    registerPromiseWorker(function)

    • function
      • Takes a message, returns a Promise or a value.

    Testing the library

    First:

    npm install
    

    Then to test in Node (using an XHR/PseudoWorker shim):

    npm test
    

    Or to test manually in your browser of choice:

    npm run test-local
    

    Or to test in a browser using SauceLabs:

    npm run test-browser
    

    Or to test with coverage reports:

    npm run coverage
    

    Install

    npm i promise-worker

    DownloadsWeekly Downloads

    19,896

    Version

    2.0.1

    License

    Apache-2.0

    Unpacked Size

    35 kB

    Total Files

    12

    Last publish

    Collaborators

    • nolanlawson