Node.js: Allow Process Update During Loop
Solution 1:
From MDN docs
The time value represents the (minimum) delay after which the message will actually be pushed into the queue. If there is no other message in the queue, the message is processed right after the delay; however, if there are messages, the setTimeout message will have to wait for other messages to be processed. For that reason, the second argument indicates a minimum time and not a guaranteed time.
Since your for loop is holding up the main thread, the message from setTimeout is not processed till the loop ends.
So timeout of 0
also gives you the same output.
setTimeout(() => cancelled = true, 0);
Solution 2:
setTimeout
is asynchronous. This means, among other things, that the event loop won't put its handler on the queue until the stack is empty.
So, setTimeout
needs two conditions to put its handler on the queue (a.k.a. run it):
1. One second elapsed from the setTimeout
call.
2. The stack being empty.
The two conditions are mandatory. setTimeout(handler, 1000)
ensures your handler won't be called before one second, but don't ensure at all that it will run after exactly one second.
On the other hand, for and while loops are blocking, i.e. they don't allow the event loop to place things onto the stack. Therefore, your handler is not being called until the for loop stops.
There is another question pretty similar to yours, that will surely help you: Why does a while loop block the event loop?
However I don't think this is exactly a duplicate, and that some extra explanation really will help you.
This youtube video about the event loop really helped me understanding this stuff: https://www.youtube.com/watch?v=8aGhZQkoFbQ
Also this nodejs docs article is pretty good: https://nodejs.org/ja/docs/guides/dont-block-the-event-loop/
Solution 3:
After some tests, this code works in an acceptable way for me.
functionAsyncLoop(start,to,fn,endFn) {
returnnewPromise((resolve, reject) => {
functionStep(i) {
var willContinue = fn(i);
if(i==to || !willContinue) {
if(endFn)
endFn(resolve, reject);
elseresolve();
return;
}
setImmediate(Step.bind(null,i+1));
}
Step(start);
});
}
var cancelled = false;
setTimeout(() => { console.log("cancel"); cancelled = true},1100);
var totalStart =Date.now();
var ret=[];
AsyncLoop(0,20, (idx) => {
var start = Date.now();
while((Date.now()-start)<100) {
v=Math.sqrt(Math.random());
}
ret.push(v);
console.log("step "+idx+":"+v);
return !cancelled;
}, (res)=>{
res(ret);
return
}).then((r)=>{
console.log("delta:"+(Date.now()-totalStart));
console.log(r.length)
});
Post a Comment for "Node.js: Allow Process Update During Loop"