You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js:循环期间如何允许进程更新?代码超时未生效问题排查

Why Doesn't My Node.js Loop Cancel After 1 Second?

Let's break down what's happening here and why your code isn't behaving as expected.

First, here's your original code for reference:

var cancelled = false;
setTimeout(() => cancelled = true,1000);
function main() {
    var ret = []
    var totalStart =Date.now();
    for(var i=0;i<20;i++) {
        var v
        var start = Date.now();
        while((Date.now()-start)<100) {
            v = Math.sqrt(Math.random());
        }
        ret.push(v);
        if(cancelled) break;
    }
    console.log("delta:"+(Date.now()-totalStart));
    return ret;
}
var r = main()
console.log(r.length)

The Root Cause: Node.js's Single-Threaded Event Loop

Node.js operates on a single thread with an event-driven model, and that's where the problem lies:

  • Your main() function is synchronous blocking code. The outer for loop and inner while loop run nonstop, hogging the only available thread from start to finish.
  • The setTimeout callback (() => cancelled = true) gets scheduled to run after 1000ms, but it can only execute once the current execution stack is empty. Since main() takes ~2000ms to finish all its synchronous work, the callback doesn't run until the loop has already completed all 20 iterations. By then, checking if(cancelled) does nothing— the loop is already done.

How to Fix It: Make the Loop Non-Blocking

To let the event loop process the setTimeout callback mid-loop, you need to break up the synchronous work into chunks that give the event loop a chance to run. Here's a modified version using async/await to yield control to the event loop after each iteration:

let cancelled = false;
setTimeout(() => cancelled = true, 1000);

async function main() {
    const ret = [];
    const totalStart = Date.now();
    
    for (let i = 0; i < 20; i++) {
        if (cancelled) break;
        
        let v;
        const start = Date.now();
        while ((Date.now() - start) < 100) {
            v = Math.sqrt(Math.random());
        }
        ret.push(v);
        
        // Yield control so the event loop can process the setTimeout callback
        await new Promise(resolve => setImmediate(resolve));
    }
    
    console.log("delta:" + (Date.now() - totalStart));
    return ret;
}

main().then(r => console.log(r.length));

Here's what changed and why:

  • We turned main into an async function, which lets us use await to pause the loop temporarily.
  • After each iteration, we await a setImmediate promise. This tells Node.js to pause the loop, handle any pending events (like the setTimeout callback), and then resume the loop.
  • Now, when the 1000ms mark hits, the setTimeout callback will run between iterations, setting cancelled to true, and the next loop check will break out of the loop as you expected.

If you prefer not to use async/await, you could also use recursive setTimeout calls to handle each iteration asynchronously, but async/await keeps the code structure close to your original while fixing the blocking issue.

内容的提问来源于stack exchange,提问作者Perry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:19:38