1

I have created a Worker in javascript that needs to loop indefinitely. Inside the loop, it needs to make several asynchronous calls and wait for them to complete before continuing on.

There are two immediate ways to do this that I can see that both seem to be fatally flawed:

1)

while(true) {
  var promise = async_call();
  while(!promise.isResolved()) { }
}

2)

var func = function() {
  var promise = async_call();
  promise.done(func);
}
func();

For #1, it falls apart because the inner while loop potentially burns up a lot of cpu; and if the thread is not interruptable, (are javascript threads interruptable? I don't think they are), then the async_call will never actually get a chance to complete, so we just get stuck in a loop.

For #2, it would work well if there was tail-call optimization, but I don't think any javascript implementations employ this, so it would quickly result in a stack overflow or other recursion limit.

Lastly, I need a way to signal to both loops when they should terminate. I can easily do this by putting a boolean stop variable into the code, but, again, that relies on the worker thread being interruptable, such that I can set stop to true.

Is there a design pattern that I have overlooked or am otherwise unfamiliar with here? How can I get my worker to execute as fast as possible without resorting to something like setInterval paired with polling isResolved?

6
  • Why would you use async calls inside worker code? Commented Dec 17, 2012 at 16:37
  • @Esailija: Why not? For example, you could handle multiple messages in parallel. Commented Dec 17, 2012 at 16:43
  • @Bergi you can just create more workers for that. As for why not, is because sync code is far more readable and you can go sync in a worker without blocking GUI. Commented Dec 17, 2012 at 16:44
  • @Esailija, in this case, I need to post a message back to the main thread and wait for it to respond. Specifically, I need to check some things against the DOM. Commented Dec 17, 2012 at 16:45
  • @davemankoff ah I see, I thought it was I/O like xhr or file reader :p Commented Dec 17, 2012 at 16:45

2 Answers 2

3

Pattern 2 is perfectly fine. It will not end up in a stack overflow if the callback is really asynchronous (some Promise libraries enforce that), as the event will be executed with a completely new stack. Only if you would synchronously call func you'd get the overflow, but you just synchronously register it as a callback.

Sign up to request clarification or add additional context in comments.

4 Comments

Is there a way to check this? Currently, I am using jQuery's Deferred simply because its handy. This is not an XHR, but instead I have to post a message back to the main thread and then wait for it to post a corresponding message back.
Actually, now that I think about it, what your saying makes sense and I think I am ok. It makes sense that the stack would reset. I guess I just needed someone to say it!
@davemankoff the way to check for it is to see if the deferred was resolved right after attaching the callback. If it was, then the deferred wasn't asynchronous.
For checking the call stack you could do a console.trace() I guess. @Esailija: Or better, directly after creation of the promise and before attaching the loop-callback :-)
0

Assuming async_call is a XHR request or setTimeout callback, you won't overflow the stack. Event callbacks (such as XHR completion) are called on a new stack; it's not really recursion.

As far as signaling the worker to stop, use message passing.

var worker = new Worker('worker.js');
// when you need to stop it:
worker.postMessage('stop');

worker.js

onmessage = function(e) {
    if (e.data == 'stop') {
        // stop
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.