I'm new in Node, so the following code behavior is not clear to me:
function step(iteration) {
if (iteration === 10) return;
process.nextTick(() => {
step(iteration + 1); // Recursive call from nextTick handler.
console.log(`nextTick iteration: ${iteration}`);
});
http.request({hostname: '127.0.0.1', port: 5000}, (response) => {
console.log("here !");
}).end();
setImmediate(() => {
console.log(`setImmediate iteration: ${iteration}`);
});
}
step(0);
OUTPUT:
nextTick iteration: 0
...
nextTick iteration: 9
setImmediate iteration: 0
...
setImmediate iteration: 9
here !
here !
here !
here !
here !
here !
here !
here !
here !
here !
Questions are:
1) why http.request()
callback is triggered after setImmediate()
? I undestand, why setImmediate()
is generally called: its callbacks were registered during the loop. But as documentation says, setImmediate()
is a check phase, which should be processed in event loop after poll one. If I understood correctly, http.request()
after nextTick()
should be that poll phase;
2) but if http.request()
is not handled in poll, in what phase does it happen? Especially considering that it works after setImmediate()
.
My Node.js version is 6.11.2. Thanks in advance for explanation.
To answer your questions:
http.request()
is called before setImmediate()
. However, http.request
is asynchronous. In your case, the callback is not run until after the request resolves. This means that although it is called first, the callback does not log anything until a later point in time—and that point is after the setImmediate()
has resolved.setImmediate
queues its callbacks for execution in the order they are queued, they still are able to resolve before the request returns.In order to handle your steps in order, consider moving the contents of the nextTick
to within the callback for the request:
function step(iteration) {
if (iteration === 10) return;
http.request({hostname: '127.0.0.1', port: 8000}, (response) => {
console.log("here !");
step(iteration + 1); // Recursive call from nextTick handler.
console.log(`nextTick iteration: ${iteration}`);
}).end();
setImmediate(() => {
console.log(`setImmediate iteration: ${iteration}`);
});
}
step(0);
In that snippet, I've removed the nextTick
, although you can safely add it in to the callback if needed.