Run in a worker#
Keep your UI responsive while a large project is leveled or evaluated by moving the Project to a worker thread.
Every Project method is synchronous and runs on the thread that calls it. A long level or evaluate call on the main thread blocks rendering and input until it returns. Inside a worker, the same call blocks only the worker.
Prerequisites#
- A bundler or runtime that loads module workers: a modern browser, or Node 18 or later.
- Data that's already plain objects. Inputs and results cross the thread boundary with
postMessage, so they must be structured-cloneable.ProjectData, change sets and all results are plain objects, arrays, strings, numbers andDates, so they qualify.
Steps#
-
Create the worker file. It owns one
Project, calls the requested method, and posts back either the result or the error fields:// scheduler.worker.js const = new; ;Send the error as plain fields. A thrown
InputErrororProjectErrordoesn't keep its class,kind,pathorcodeafterpostMessage.You don't need to call
init(); it loads nothing and resolves immediately. -
On the main thread, start the worker and wrap each message in a promise:
const = new; let = 0; const = new; ; -
Call the project methods through
callandawaitthe results:.; -
Check errors by
nameinstead ofinstanceof. A rejected call carries the fields the worker sent:
Keep the calls for one project in a single worker. The worker handles messages one at a time, so the calls run in the order you send them, as they would on the main thread.
evaluate scores candidates one after another, and one worker runs one evaluation at a time.
Node: use worker_threads#
In Node, the worker talks to parentPort instead of self. The method calls and messages stay the same:
// scheduler.worker.js
const = new;
;
// main.js
const = new;
;
Result#
level runs in the worker, and the main thread stays free to render and handle input. leveled.updates arrives as the same plain objects a direct call returns:
2 [{"end_date":"2026-08-19 08:00","id":"a","kind":"task","pauses":[{"at":2,"by":"leveling","length":2}]}]
If you create the project with new Project({ dates: "date" }), result dates arrive as Date objects too, because postMessage copies Dates.