-
-
Save scottnonnenberg/56597f27c6cd44dfbfee to your computer and use it in GitHub Desktop.
2015-03-23T19:41:49.232Z | |
2015-03-23T19:41:49.367Z | |
2015-03-23T19:41:49.470Z | |
2015-03-23T19:41:49.571Z | |
sync task start | |
sync task done | |
2015-03-23T19:41:50.632Z | |
2015-03-23T19:41:50.733Z | |
2015-03-23T19:41:50.834Z | |
^C |
setInterval(function() { | |
var now = new Date(); | |
console.log(now.toJSON()); | |
}, 100); | |
setTimeout(function() { | |
var start = new Date(); | |
var now = new Date(); | |
console.log('sync task start'); | |
while (now.getTime() - start.getTime() < 1000) { | |
now = new Date(); | |
} | |
console.log('sync task done'); | |
}, 500) |
It's fair to argue from the documentation, but it's also fair to argue from user expectation. setInterval(fn, 100)
is often expected to mean 'run this 10 times per second.' Thus, an interruption in the event loop of 1 second breaks that expectation - expected calls are dropped completely.
Hey @scottnonnenberg,
Thanks for the snippet — really useful when explaining some of the Node.js aspects!
I agree with @davisjam, "dropped" isn't the right word here. It becomes more clear with the following patch:
diff --git a/skipped_setInterval.js b/skipped_setInterval.js
index 948fe0d..26f5d8d 100644
--- a/skipped_setInterval.js
+++ b/skipped_setInterval.js
@@ -1,6 +1,8 @@
+var counter = 0;
+
setInterval(function() {
var now = new Date();
- console.log(now.toJSON());
+ console.log(counter++, now.toJSON());
}, 100);
setTimeout(function() {
which will result in the following output:
0 '2017-09-06T09:53:34.177Z'
1 '2017-09-06T09:53:34.291Z'
2 '2017-09-06T09:53:34.393Z'
3 '2017-09-06T09:53:34.496Z'
sync task start
sync task done
4 '2017-09-06T09:53:35.573Z'
5 '2017-09-06T09:53:35.675Z'
6 '2017-09-06T09:53:35.780Z'
^C
Rephrasing official documentation
Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering.
The callback will be called as close as possible to the time specified.
we should read that as "the callback will be called not earlier than the specified interval".
Everything runs in parallel except for our code ;)
Best,
Max
Why would callbacks being called out of order? I assumed it was a single thread model, so the callbacks should be executed off one stack.
If callbacks can be called out of order, that would make shared state more difficult to manage.
I don't think "dropped" is really the right turn of phrase here. setInterval CBs get run at a particular point in the event loop (during timer handling way down in libuv). If the event loop is blocked due to synchronous work, the setInterval CBs will be delayed until the work is finished.
The relevant information from the Node.js docs can be found in setTimeout:
In your example, each setInterval CB is invoked as close to 100ms after the previous one as possible. It just so happens that the synchronous work means that "1 second" later" is the best Node.js can do.