nik
nik

Reputation: 303

How to create a subworker?

Read a lot of articles, but none of those give a clear answer how to create a subworker? As I understood there is a way to do it right out of one webworker, but the only way I found is installScript(), though it seems to be more of a script injection. Ca someone share an example how to create one and how workers communicate between each othee?

Upvotes: 0

Views: 1636

Answers (1)

M. Neuweiler
M. Neuweiler

Reputation: 76

A subworker is spawned exactly the same way a normal dedicated worker is created:

var worker = new Worker("worker.js");
worker.onmessage = function(event) {
    ...
};

and messages are also sent the same way to the subworker from within the worker, e.g.

worker.postMessage({cmd: 'start'});

You can find an example at https://html.spec.whatwg.org/multipage/workers.html#delegation (incl. a link to test it). But the only browsers which support subworkers at the moment are Firefox and Edge. Chrome, Safari, Opera and Android Browser (Nougat) don't implement this feature yet unfortunately although it could greatly help to further enhance the performance on multi-core systems.

According to a 7 year old issue for Chrome, it doesn't seem likely that they're going to implement this part of the specification.

If you want to maintain browser compatibility, the only approach is to spawn all workers from the main thread (which also manages the DOM/UI) and burden it with routing the messages back an forth.

Assuming you would like to create a worker called "handler" which then spawns subworkers and routes messages back and forth, you could change the handler to a pseudo worker (not in separate thread) but keep the code changes to a minimum by adding this code at the top of "handler" and instantiating it with new PseudoWorker(); instead of new Worker("handler.js"); (of course you'd have to add a JS reference to "handler.js" in your webpage so it'll be able to find the class PseudoWorker) :

// begin of PseudoWorker wrapper
var parentOnmessage;
var PseudoWorker = function() {
    var initialized = false;

    this.postMessage = function(msg) {
        self.onmessage({data: msg});
        if (!initialized) {
            self.parentOnmessage = this.onmessage;
            initialized = true;
        }
    } 
}

this.postMessage = function(data) {
    parentOnmessage({data: data});
}
// end of PseudoWrapper - add your code after this line as if this was a normal worker

The only caveat would be that the PseudoWorker would not start to work automatically but only after it received a message. This is so the variables can be properly initialized. But the code works on all above mentioned browsers. You can switch back from PseudoWorker to a normal worker as soon as the browsers support subworkers.

Upvotes: 3

Related Questions