Skip to content
easy-web-worker

Methods and the message

The three ways to write a worker method, what the message of a call offers, and the controls behind the methods.

GuideTypeScriptTry an example

Three ways to write a method

worker.ts
import { defineWorker } from 'easy-web-worker/defineWorker';

const worker = defineWorker(({ onMessage }) => ({
  // 1. a plain function: the returned value resolves the call
  double: (value: number) => value * 2,

  // 2. onMessage: the same, with the message and the event typed for you
  count: onMessage(async (to: number, message, event) => {
    message.reportProgress(50, { messageId: event.data.messageId });

    return to;
  }),

  // 3. onMessage().handle: only the message, and you complete it
  wait: onMessage<number, string>().handle((message) => {
    const timeoutId = setTimeout(() => message.resolve('done'), message.payload);

    message.onCancel(() => clearTimeout(timeoutId));
  }),
}));

export type ThreeWaysWorker = typeof worker;
StyleCompletes the callTypes
Plain functionWith the returned valueInferred
onMessage((payload, message, event) => ...)With the returned valueInferred, message typed
onMessage<P, R>().handle((message) => ...)You doExplicit, message.resolve typed

All three are called the same way from the main thread.

  • Use a plain function when the method only needs its payload.
  • Use onMessage when it also reports progress or reacts to a cancellation. The wrapper exists to give the second parameter its type; a plain function receives the same arguments.
  • Use onMessage().handle for timers, streams and event-based APIs, or to transfer a result.

A method with no payload

To reach the message without a payload, declare the first parameter as null.

status.worker.ts
import { defineWorker } from 'easy-web-worker/defineWorker';

const worker = defineWorker(({ onMessage }) => ({
  // the payload is declared as null to reach the message
  status: onMessage((_payload: null, message) => {
    message.reportProgress(50);

    return 'ready';
  }),
}));

export type StatusWorker = typeof worker;

The message

Available as second parameter of a method, in .handle(...), and in the message API.

MemberPurpose
payloadValue sent from the main thread
resolve(result?, transfer?)Resolves the call
reject(reason?, transfer?)Rejects the call
cancel(reason?, transfer?)Cancels the call from inside the worker
reportProgress(percentage, payload?, transfer?)Reports progress and keeps the call pending
onCancel, onResolve, onReject, onProgressSubscribe to each outcome; return unsubscribe
onFinalizeRuns once the call ends, whatever the outcome
isPending(), getStatus()Current state of the call

onFinalize is the place to release what a call opened:

watch.worker.ts
import { defineWorker } from 'easy-web-worker/defineWorker';

const worker = defineWorker(({ onMessage }) => ({
  watch: onMessage<string, void>().handle((message) => {
    const source = new EventSource(message.payload);

    source.onmessage = (event) => message.reportProgress(0, event.data);
    source.onerror = () => message.reject(new Error('Connection lost'));

    // runs once, whether the call was resolved, rejected or canceled
    message.onFinalize(() => source.close());
  }),
}));

export type WatchWorker = typeof worker;

The event

The third parameter of a method is the original MessageEvent received by the worker. It is rarely needed; it is there for code that inspects the raw message.

The controls behind the methods

The object returned by defineWorker describes the methods. unwrap reaches the worker behind it: onMessage for messages sent without a method, importScripts and close.

ping.worker.ts
import { defineWorker, unwrap } from 'easy-web-worker/defineWorker';

const worker = defineWorker(() => ({
  ping: () => 'pong',
}));

// the worker-side controls behind the methods
unwrap(worker).importScripts('https://example.com/library.js');

// handles the messages sent without a method: send, override, overrideAfterCurrent
unwrap(worker).onMessage((message) => {
  message.resolve();
});

export type PingWorker = typeof worker;

The same helper works on the main thread, where it returns the EasyWebWorker instance. See the API reference.

Documentation
↑↓ Navigate ↵ Open Esc Closeeasy-web-worker docs
Get started

Real Web Workers. Typed methods.
Cancelable promises.