Use promise in a Web Worker

1

To use Web Workers for certain things, can you use a promise for when it's done?

Type like this

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

nonce would be the value returned by the message.

    
asked by anonymous 16.04.2015 / 01:48

2 answers

3

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

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

Main page code:

// 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>

worker code :

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 working example, use this HTML snippet "test.html" and this JavaScript code " worker.js ". Note: A webserver is required for the example to work, you can not load a worker from file:/// (in Chrome at least).

    
16.04.2015 / 03:05
1

It is not possible, as there is no mention of any promises in the WebWorkers API . .

The worker has nothing of promise implemented and is not an asynchronous processing like ajax. You can only talk to him through messages.

    
16.04.2015 / 02:55