-
Notifications
You must be signed in to change notification settings - Fork 7.3k
setTimeout(fn, 0) running before setImmediate #6034
Comments
Documentation bug (but a small one). The event loop cycle is timers -> I/O -> immediates, rinse and repeat. The documentation is correct but incomplete: it doesn't mention that when you haven't entered the event loop yet (as is the case in your example), then timers come first - but only on the first tick. (In master. To complicate matters, things work slightly less deterministic in v0.10.) If you wrap your example in another timer, it always prints setImmediate followed by setTimeout. setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10); |
@bnoordhuis Would you explain the event loop cycle more explicitly? When have entered event loop, what's the priority of timers, I/O and immediates? In your code above
Follow the cycle you mentioned above:
The code will be executed like this:
Result should be
But actually, result is
Would you tell me where is the place I misunderstanding? Thanks. |
+1 good graph, thx @rlidwka |
If on the above graph |
timers are based on a time in the future, even if it's 0, while check immediate is always on the next turn of the loop. So it's possible that the delay of the event loop is low enough for the timer to fire after the immediate. You shouldn't necessarily be concerned about the order of operations in this regard though in my estimation. |
One correction. |
re #5950 |
I think this is the best answer to my question. Thank you, @tjfontaine |
You're welcome. You might also want to thank a real author of that image, though I have no idea who he is. :-) |
Thanks @rlidwka, but the image is broken. Could you still find the graph? |
Thanks, @rlidwka! |
Having different behavior on first tick is a real problem. In a-synchronous systems, a frequently occurring design pattern is what I call "sentinel event". When you cancel an a-synchronous operation, there is a race condition between the operation completing and the operation being cancelled. To avoid this, you introduce an extra callback to signal completion of the cancel() method. This callback should always arrive AFTER a possible completion callback, so that the caller knows when not to expect callbacks anymore. How can this be realized in Node? Is it guaranteed that using setTimeout(cancelCallback, 0) always arrives after any previous completion callbacks scheduled with nextTick, setImmediate, or I/O result? |
@rogierschouten The fact you bring up We don't guarantee that any differing set of asynchronous functions run before any other. The only guarantee is that in the case: setTimeout(function A() { }, 10);
setTimeout(function B() { }, 20); Function @kesla It's incorrect to say that the |
@trevnorris ... is this something we still need to keep open? |
nope |
Running
will result in
even though the current docs state that "To schedule the "immediate" execution of callback after I/O events callbacks and before setTimeout and setInterval." (http://nodejs.org/docs/latest/api/all.html#all_setimmediate_callback_arg)
Are the docs unclear or is this a real bug?
cc @trevnorris
The text was updated successfully, but these errors were encountered: