Use Promise in a Web Worker

Asked

Viewed 227 times

1

TO using Web Workers for certain things, has how to use a Promise for when it finishes running?

Kind of

WR.postMessage({taskID: 'g_b_i'}).then(function(nonce){
        console.log(dT(), 'Sending parameter nonce: ', nonce);
    });

the nonce would be the value returned by the message.

  • That’s javascript, but Node.js right? If you add the Node.js tag to the question, you’re more likely to get a good answer to your problem. And if not ignore. = D

  • 1

    is pure JS even, didn’t use Node.js @Fernando Thanks!

2 answers

3


The method WebWorker.postMessage does not return anything ("Void"), so that it cannot be used directly this way. If you want to use promises, you’ll have to implement it yourself.

One way to do this is by associating to each message you send to web worker a single ID, and at the end of every run the worker sends the result also accompanied by this unique ID. Then just call the method resolve or reject associated with that ID, whether the task has been successful or not (this has to be indicated by the task itself worker, naturally).

Code of the main page:

// Simulação de um webWorker (para testes)
var WR = {
    postMessage: function(event) {
        event = { data:event };

        var data = event.data;
        // Faz alguma coisa com data.dados
        setTimeout(function() {
            if ( Math.random() < 0.7 )
                WR.onmessage({ data:{ ok:data.msgid, dados:"dados " + data.msgid }});
            else
                WR.onmessage({ data:{ falhou:data.msgid, dados:"outrosdados " + data.msgid }});
        }, Math.floor(Math.random() * 3000));
    }
}

// Implementação
var msgseq = 1;
var callbacks = {};
function postWithPromise(WR, dados) {
    return new Promise(function(resolve, reject) {
        var id = msgseq++;
        WR.postMessage({ msgid: id, dados:dados });
        callbacks[id] = { resolve:resolve, reject:reject };
    });
}
WR.onmessage = function(event) {
    var data = event.data;
    if ( data.ok ) {
        callbacks[data.ok].resolve(data.dados);
        delete callbacks[data.ok];
    }
    if ( data.falhou ) {
        callbacks[data.falhou].reject(data.dados);
        delete callbacks[data.falhou];
    }
}

// Exemplo de uso
document.querySelector("button").onclick = function() {
    postWithPromise(WR, "dados").then(function(dados) { 
        alert("OK (" + dados + ")");
    }, function(dados) {
        alert("Falhou (" + dados + ")");
    });
};
<button>Testar</button>

Code of worker:

self.onmessage = function(event) {
    var data = event.data;

    // Faz alguma coisa com data.dados

    if ( Math.random() < 0.7 )
        self.postMessage({ ok:data.msgid, dados:"dados " + data.msgid });
    else
        self.postMessage({ falhou:data.msgid, dados:"outrosdados " + data.msgid });
}

For a functional example, use this [fragment of] HTML "html test." and this Javascript code "worker js.". Note: it takes one webserver for the example to work, one cannot load a worker from the file:/// (in Chrome at least).

  • I did not understand the use of setinterval..

  • @user3163662 I can’t create an example in Stack Snippets (or even jsFiddle) with a web worker actually, as I would need an external . js file, so I "simulated" a web worker using setTimeout (The answer is to arrive asynchronously, as it would be in real use). No web worker real, the setTimeout is unnecessary.

  • I did a "gambiarra" passing the code that should be executed at the end in string form and then running it in "onmessage"

  • I tried to use your code but I can’t understand it, can you clear it using real code? It doesn’t have to work here, just so I really understand

  • @user3163662 I tweaked some of the code to look more like the real code (the events of web worker pass the data on a property data, not direct at the event) and put two files in the Pastebin with a functional example (tested here, in Chrome, and everything looks ok).

  • I understand better, it’s quite functional, thank you!

Show 1 more comment

1

It is not possible, as there is no mention of any Promises in API of Webworkers.

The worker has nothing implemented and is not asynchronous processing like ajax. It is possible to talk to him only through messages.

  • In reality he is asynchronous processing as ajax... The rest of the answer is correct, however.

  • 1

    Asynchronous, yes, but not like ajax. Webworker is a "parallel process" for the browser, the common asynchronous runs in "threads" by the interpreter.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.