Search code examples
javascriptweb-worker

Sending another postMessage in worker.addEventListener


Main question: is calling worker.postMessage from the worker.addEventListener bad? Example below, I tried to keep it as short as possible.

I have a GWT native function with a worker (worker is initialized before so I can reuse it. Also, the braces should be /*-{ and }-*/ but for the sake for syntax highlighting I just go with {}).

private native void nativeWorkerCalls(JavaScriptObject worker, int cwidth, int cheight) {
    console.log('Main: Pre draw');
    worker.postMessage({'cmd' : 'draw', 'args' : [cwidth*cheight] });
    
    worker.addEventListener('message', function(e) {
        switch (e.data.cmd) {
            case 'draw':
                /* do some stuff */
                console.log('Main: Pre clear');
                worker.postMessage({'cmd' : 'clearBuffer', 'args' : [e.data.offset]}); // I call the worker again!
                break;
            case 'clearBuffer':
                console.log("%c Main: Post clear", 'background: #222; color: #00ffae');
                break;
            default:
                break;
        };
        console.log("Main: ### Finished listener ###");
    }, false);
};

and following worker.js script which should execute different switch cases depending on the 'cmd' passed.

importScripts("emscripten.js");

self.addEventListener('message', function(e) {
    var data = e.data;
    switch (data.cmd) {
        case 'draw':
            /* assign some buffer, draw into it */
            self.postMessage({ 'cmd' : 'draw', buffer : mb, offset : buffer});
            break;
        case 'clearBuffer':
            /* clear buffer */
            console.log('Main: Pre clear');
            self.postMessage({'cmd' : 'clearBuffer'});
            break;
        default:
            self.postMessage(null);
        };
}, false);

Problem: The first time I run the native function it's all fine. But every following call has the side effect that the eventlistener in worker.js gets called repeatedly.

One run should make following calls:

Main: Pre draw

Worker: Draw

Main: Post draw

Main: Pre clear

Main: ### Finished listener ###

Worker: Free buffer

Main: Post clear

Main: ### Finished listener ###

Pressing the button a second time gives me too many calls - it adds another draw (which doesn't seem to do anything) and also adds another clear (which runs into an error because the worker will then try to free a buffer that has already been freed):

Main: Pre draw

Worker: Draw

Main: Post draw

Main: Pre clear

Main: ### Finished listener ###

Main: Post draw

Main: Pre clear

Main: ### Finished listener ###

Worker: Free buffer

Main: Post clear

Main: ### Finished listener ###

Main: Post clear

Main: ### Finished listener ###

Worker: Free buffer


Solution

  • Stupid mistake on my behalf. The reason why I had these extra calls was because I kept adding event listeners to the worker. Obviously I need to add the event listener where I instantiate the worker and then I can pass the worker around.