Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a return value back from a web worker

Right now, I've got this, and it works:

var myWebWorker = new Worker('myWebWorker.js');
myWebWorker.onmessage = function (myEvent) {
    $('#Print').append('Return value: ' + myEvent.data + "<br>");
};
myWebWorker.postMessage(2);

My question is: Can I do this instead?

var result = myWebWorker.postMessage(2);

Because I need the web worker to be synchronous - in other words, give a return value and also don't return until you're finished.

Edit 1:

The web worker is doing an insert/select onto a local database using openDatabaseSync transactions.

Edit 2:

It appears that my problem is with Cocoa Touch and not with JavaScript. Here's a clever hack that someone has posted on StackOverflow.

Edit 3:

Here's a better hack.

like image 958
Phillip Senn Avatar asked Jan 13 '23 21:01

Phillip Senn


2 Answers

The point of web workers is to delegate tasks without blocking the UI. They can't be synchronous.

You probably don't need the task to be synchronous but you need to design your code around events and asynchronous tasks just like you can't design any javascript application nor any serious GUI application with only synchronous operations.

like image 132
Denys Séguret Avatar answered Jan 19 '23 11:01

Denys Séguret


As already said, you can't call the worker synchronously. You could write a wrapper that waits for the worker to return a message, but that has the same effect as executing the worker's code directly in you caller's code. The caller would be blocked for the time the worker code runs.

When you should use workers:

CPU1  CPU2    Explanation
 A            # Main script starts (in one Thread/CPU)
 |            # still runs...
 |---->B      # Offload some heavy work to Worker B (to another Thread/CPU)
 |     |      # A can do other stuff while B does some heavy work that would block A
 |<----B      # B is ready and posts the result to A
 |            # A is interrupted only shortly by B's message
 V

I hope this makes things clearer.

I am hesitating to add this code (i.e., please rethink your need for calling a Worker synchronously), but even writing a sync wrapper does not work (Thx to the commenters):

function syncMe(){
    var w = new Worker('myWebWorker.js');
    var data = null, ready = false;
    w.onmessage = function (e) {
        ready = true;
        data = e.data;
    };         
    w.postMessage(2)
    while(!ready){ /* block this thread forever, since `ready` is never changed */ }
    console.log(data);
}

Edit: "Why You can't sync a worker like this"

The onmessage handler will never be called because the JavaScript VM can only call one function a time and the syncMe function has not yet exited. (Sorry for the confusion)

like image 37
Juve Avatar answered Jan 19 '23 12:01

Juve