AndersCan / typed-web-workers

Create web workers with type safety
MIT License
28 stars 0 forks source link
typescript web-worker

typed-web-workers

npm versionDependabot Statuscode style: prettier

Library that help you get quickly up and running with web workers in TypeScript or JavaScript projects.

❗️❗️❗️ The workerFunction is executed in an isolated context. It can not rely on its surrounding context. Use importScripts if you need something added to the worker context

Installation

npm install typed-web-workers

tl;dr

import { createWorker } from 'typed-web-workers'

const worker = createWorker({
  workerFunction: ({input, callback}) => callback(input * 2),
  onMessage: result => console.log(`Worker returned: ${result}`),
  onError: error => console.log(`unhandled exception in Worker`)
})
worker.postMessage(1) // Worker returned: 2
worker.postMessage(2) // Worker returned: 4

Only workerFunction is required by createWorker.

Fiddles

ESM example, IIFE example

Motivation for Web Workers

When the main thread is blocked, the UI will be unresponsive to user events.

Note Using a web worker does not make a function run faster.

Motivation for Typed Web Workers

Usage

Worker with local state

/**
 * Function that will be executed on the Worker
 * */
function workerFunction({
  input,
  callback,
  getState,
  setState
}: WorkerFunctionProps<number, number, number>) {
  const previousValue = getState() || 0
  callback(previousValue + input)
  setState(input)
}

 createWorker({
  workerFunction,
  onMessage: data => console.log(data)
})

Worker with moment.js

const momentWorker = createWorker({
  workerFunction: ({input,callback}) => callback(moment(input).format('YYYY')),
  onMessage: data => console.log(data)
  importScripts: [
    'https://unpkg.com/moment@2.22.2/min/moment.min.js'
  ]
})

importScripts

Use importScripts to import external files into your Worker (mdn docs).

The provided URIs in importScripts must link to a JavaScript file that can be loaded by the Worker at runtime. The scripts must be CommonJs/umd as Workers do not support ES modules.

If something goes wrong during the import an exception will be thrown and onError will be called. If this happens, you can assume the worker is no longer responsive.

Using local files

How you solve this depends on how you build and deploy your project.

You will most likely need to create a new entrypoint bundle that you can import with importScripts. For example importScripts["www.example.com/public/my-script.js"].

Worker Scope

The workerFunction that we give our worker can only use the data provided from the input variable, from its state and from importScripts. It does not have access to variables or functions outside its scope.

const results = []
function workerFunction({input, callback}) {
  results.push(input.x + input.y) // this would not work
}

It will compile, but would not work because the two variables are not in the same context/thread.

const results = [] // main context
function workerFunction({input, callback}) {
  results.push(input.x + input.y) // worker context
}

How does this work?

In short, createWorker:

  1. Converts your workerFunction to a string
  2. Creates a new native Worker using this string (by using Blob)
  3. returns a instance of a TypedWorker that acts as a wrapper to the native worker.

Check the source code of TypedWorker.ts if you want more information.