@mafintosh asks: "Does anyone have a good code example of when to use setImmediate instead of nextTick?"
The answer is "generally anywhere outside of core".
process.nextTick is barely asynchronous. Flow-wise it is asynchronous, but it will trigger before any other asynchronous events can (timers, io, etc.) and thus can starve the event loop.
In this script I show a starved event loop where I just synchronously block, use
bryce@x1c:~/tmp$ /usr/bin/time node starved.js blocked I took 1608.396358ms, expected to take 10 1.68user 0.00system 0:01.69elapsed 99%CPU (0avgtext+0avgdata 24016maxresident)k 0inputs+0outputs (0major+3572minor)pagefaults 0swaps
bryce@x1c:~/tmp$ /usr/bin/time node starved.js nexttick I took 1611.755809ms, expected to take 10 1.68user 0.00system 0:01.70elapsed 99%CPU (0avgtext+0avgdata 24024maxresident)k 0inputs+0outputs (0major+3572minor)pagefaults 0swaps
bryce@x1c:~/tmp$ /usr/bin/time node starved.js setimmediate I took 144.870217ms, expected to take 10 1.68user 0.00system 0:01.69elapsed 99%CPU (0avgtext+0avgdata 23952maxresident)k 0inputs+0outputs (0major+3578minor)pagefaults 0swaps
nexttick behave the same -- the
setTimeout is delayed until after all calls to the blocking
Even though we're scheduling more
process.nextTick calls asynchronously, nothing can get inserted between them on the event loop.
setImmediate example is not blocked as long because the
setTimeout gets run between consecutive
setImmediate calls, and even though it is late (the
run function is slow enough to delay it on its own) it still gets through.