I've read this nice doc guide: https://nodejs.org/en/docs/guides/dont-block-the-event-loop/
And in some part of that article it's being said regarding to complex calculations without blocking the Event Loop:
Suppose you want to do complex calculations in JavaScript without blocking the Event Loop. You have two options: partitioning or offloading. You could partition your calculations so that each runs on the Event Loop but regularly yields (gives turns to) other pending events.
And they gave as an example this code example to calculate the avg of 0 + 1 + 2 +... + n:
function asyncAvg(n, avgCB) {
// Save ongoing sum in JS closure.
var sum = 0;
function help(i, cb) {
sum += i;
if (i == n) {
cb(sum);
return;
}
// "Asynchronous recursion".
// Schedule next operation asynchronously.
setImmediate(help.bind(null, i+1, cb));
}
// Start the helper, with CB to call avgCB.
help(1, function(sum){
var avg = sum/n;
avgCB(avg);
});
}
asyncAvg(n, function(avg){
console.log('avg of 1-n: ' + avg);
});
My questions are:
The setImmediate
will be executed If the poll phase scripts have been scheduled by setImmediate()
, then the event loop will end the poll phase and continue to the check phase to execute those scheduled scripts.
but if we are in the recursive step:
function help(i, cb) {
sum += i;
if (i == n) {
cb(sum);
return;
}
// "Asynchronous recursion".
// Schedule next operation asynchronously.
setImmediate(help.bind(null, i+1, cb));
}
then the poll should be empty but the setImmediate
command, and therefore it should keep running the recursive, so how would it give opportunity to other code to be executed meanwhile? in terms of event-loop scheduling.
n
there isn't RangeError: Maximum call stack size exceeded
error, but if I change this line:setImmediate(help.bind(null, i+1, cb));
to this line:
help(i+1, cb);
then the error RangeError: Maximum call stack size exceeded
pops up. I mean, using the setImmediate
should anyway keep the functions stack caused by the recursive, no?
then the poll should be empty but the setImmediate command, and therefore it should keep running the recursive, so how would it give opportunity to other code to be executed meanwhile?
Because setImmediate
schedules callbacks to happen just after the poll
phase completes. Those callbacks are run during the check
phase. Adding more callbacks during check
schedules them, but doesn't cause them to run; that happens the next time the loop gets to the poll
phase, sees there are pending callbacks, and enters the check
phase.
Why for really big n there isn't RangeError: Maximum call stack size exceeded error
Because the recursion isn't immediate, so it doesn't consume stack space. setImmediate
just schedules a callback, it doesn't call the callback. Your code ends, releasing its stack resources, and the event loop continues. Later, the callback you scheduled via setImmediate
gets run, briefly using a small bit of stack space.
In contrast, when you call help
immediately, that's allocating a new stack frame, and if you use a big n
, you allocate too many stack frames and run out of stack.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.