-
Notifications
You must be signed in to change notification settings - Fork 7.3k
[timers] setImmediate executes after setTimeout #25788
Comments
Thanks @a0viedo for taking the time to file an issue! It's a duplicate of #6034. What happens with the code you mentioned is that the timer and the immediate are added, and then the libuv event loop starts. When it starts, the libuv event loop first check for timers, and if the time between when a timer was added and when the event loop starts is greater than the timer's timeout value, then that timer will fire before any immediate. The output is not consistent because it depends on the timing of these operations: sometimes the timer will fire before the immediate, sometimes it will be the other way around. There are other ways this inconsistency could be reproduced. This issue has been present for a while (including in v0.10.x versions), and hasn't been introduced recently. Maybe what the docs should highlight is that the guarantee is that
However, scheduling the same operations differently doesn't guarantee any ordering between timer callbacks and immediate callbacks. There are other guarantees made by immediates, such as the fact that immediates scheduled within another immediate are called on the next turn of the event loop. However, I'm not sure having a stronger contract than that would have any significant impact on users, so I would think that this doesn't need to be fixed in code. Do you have a use case that this bug makes impossible to manage? |
Thanks @misterdjules! That gave a lot of insight on the use case. I think we could improve the docs to say the same you wrote here. Another quick question, in the case of using process.nextTick(function() {
setTimeout(function() {
console.log('timeout')
}, 0)
setImmediate(function() {
console.log('immediate')
})
}); |
@a0viedo The same problem arises in the example above (scheduling a timeout and an immediate in the callback of The reason is that when that |
I looked at #6034 and seems like it's not guaranteed that it will run always before: @trevnorris wrote:
So I created assertImmediate.js: var assert = require('assert');
var i;
setTimeout(function() {
var called = false;
function callback(caller) {
if (called) {
assert.equal(caller, 'timeout');
} else {
called = true;
assert.equal(caller, 'immediate');
}
}
setTimeout(callback.bind(null, 'timeout'), 0)
setImmediate(callback.bind(null, 'immediate'))
}); And running that several times:
will throw with some probability an AssertionError. Is that the expected behavior, that will have high chances of running before any other timer? |
Exactly, and it's in line with my previous comments on this issue. The Like I said before, I'm not sure there's any value in "fixing" these use cases, but any feedback on that is more than welcome. |
Is this a known issue? From the docs:
But this code
outputs first
timeout
in v0.12.5.The text was updated successfully, but these errors were encountered: