Posting a message to a web worker while it is still running

Say we have a web worker referring to a file called "worker.js". We use the worker to execute a function in "worker.js" that does some lengthy operation. We call post the respective message to the worker and proceed in the main thread. However, before the worker has finished doing its initial work, the main thread posts another message to it.

My question: Will the worker continue with our time-taking function and only process the newly posted message once finished or will it interrupt its current operation until the new one has been completed?

Answers:

Answer

I've tried out the following code in Google Chrome's debugger:

worker.js:

var cosine;
self.onmessage = function(e) {
    if (e.data.message == 0) {
        for (var i = 0; i < 10000000; i++) {
            cosine = Math.cos(Math.random());
            if (i % 1000 == 0) console.log("hello world");
        }
    } else if (e.data.message == 1) {
        console.log("xyz");
    }
};

main.js:

var worker;

function main() {
    worker = new Worker("js/worker.js");
    worker.postMessage({message: 0});
    setTimeout(xyz, 10);
}

function xyz() {
    worker.postMessage({message: 1});
}

output:

(10000 times) test.js:11 hello world
test.js:14 xyz

The cosine variable is recalculated with every new iteration to provide the "time-taking" algorithm described in the question. Apparently, the message is only received as soon as the last operation has finished, as I observed the "xyz" output being printed immediately after the 10000th "hello world" output.

Answer

A Web Worker is backed by a single thread. This means that while the "onmessage" handler is being executed, it will not be able to receive another "onmessage" event until the previous one has finished.

This is quite inconvenient if we want to implement some background computation process that we want to be able to pause and resume, because there is no way to send a "pause" message to a running worker. We are able to stop a web worker via worker.terminate(), but that completely kills the worker.

The only way I can think of is by slicing worker execution into chunks, then post a message from the worker at the end of each chunk, which then triggers a message to the worker to process the next chunk, and so on.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.