I'm not really sure if I understand your question.
If you want your web worker to be stateful and perform different tasks according to the message the main thread sent to the worker, you will need to implement your own messaging system. You will need to establish some kind of convention for your messages, and use some way to distinguish between the incoming messages, both in the main thread and in your web worker. Basically you need to implement a very lightweight version of Redux.
For example, I wrote a Three.js app where I render a bitmap in an OffscreenCanvas in a web worker.
First, I established a convention for the messages exchanged between main thread and worker. All my messages have a string representing the action
the message is all about, a payload
containing some optional data, and a source
stating who sent the message (i.e. the main thread or the web worker).
In my app, the main thread can send 2 types of messages to the worker, while the worker can sen 3 types of messages.
// Actions sent by main thread to the web worker
export const MainThreadAction = Object.freeze({
INIT_WORKER_STATE: "initialize-worker-state",
REQUEST_BITMAPS: "request-bitmaps"
});
// Actions sent by the web worker to the main thread
export const WorkerAction = Object.freeze({
BITMAPS: "bitmaps",
NOTIFY: "notify",
TERMINATE_ME: "terminate-me",
});
My web worker is stateful, so in my worker.js
file I have this code:
// internal state of this web worker
const state = {};
The worker can discern the messages sent by the main thread with a simple switch
statement, handle the message, and respond to the main thread with postMessage
:
// worker.js
const onMessage = event => {
const label = `[${event.data.source} --> ${NAME}] - ${event.data.action}`;
console.log(`%c${label}`, style);
switch (event.data.action) {
case MainThreadAction.INIT_WORKER_STATE:
// handle action and postMessage
break;
case MainThreadAction.REQUEST_BITMAPS: {
// handle action and postMessage
break;
}
default: {
console.warn(`${NAME} received a message that does not handle`, event);
}
}
};
onmessage = onMessage;
The code running in the main thread also uses a switch
statement to distinguish between the messages sent by the worker:
// main.js
switch (event.data.action) {
case WorkerAction.BITMAPS: {
// handle action
break;
}
case WorkerAction.TERMINATE_ME: {
worker.terminate();
console.warn(`${NAME} terminated ${event.data.source}`);
break;
}
case WorkerAction.NOTIFY: {
// handle action
break;
}
default: {
console.warn(`${NAME} received a message that does not handle`, event);
}
}