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

JavaScript中setTimeout无法获取变量更新值的问题求助

问题分析与修复方案

你的问题核心是:触发错误调用sendResponse后,虽然responseAlreadySent已设为true,但setTimeout的回调仍会执行,导致重复响应或意外行为。根源在于清除定时器的时机不够提前,或者存在竞态条件导致定时器未被及时取消。

修复方案

最直接的解决方式是:在sendResponse函数最开始就清除定时器,确保任何触发sendResponse的操作都会先阻止超时回调执行,再处理响应逻辑。同时补充代码中缺失的res参数(原代码未传入该变量,会导致运行时错误)。

修改后的代码如下:

const handleProcessError = (processName, process, res) => {
    let responseTimeout;
    let responseAlreadySent = false;

    const sendResponse = (status, message, scan_id, scantype, error) => {
        // 优先清除定时器,从根源避免超时回调执行
        clearTimeout(responseTimeout);
        
        if (!responseAlreadySent) {
            responseAlreadySent = true;
            if (status === 'Success') {
                console.log('Sending success response', responseAlreadySent);
                res.status(200).json({ status, message });
            } else {
                console.log('Sending error response', responseAlreadySent);
                res.status(500).json({ status, message });
                revertScanAndThrowError(error, processName);
            }
        } else {
            console.log('Response already sent, skipping');
        }
    };

    responseTimeout = setTimeout(() => {
        sendResponse('Success', 'The scan started', inc_val, scantype);
    }, 5000);
    
    let errorOutput = '';
          
    process.stderr.on('data', (data: Buffer) => {
        errorOutput += data.toString();
    });

    process.on('exit', (code: number, signal: NodeJS.Signals) => {
        if (code !== 0) {
            sendResponse('Error', 'Failed to start the scan', null, null, new Error(`Process exited with code ${code}. Error output: ${errorOutput}`));
        } else {
            console.log(`${processName} process exited with code 0`);
        }
    });

    // Other event listeners and handlers...
};

关键修改说明

  1. 提前清除定时器:将clearTimeout(responseTimeout)移到sendResponse的最开头,无论是否需要发送响应,都会先取消超时任务,彻底避免后续回调执行。
  2. 补充res参数:原代码中sendResponse使用了res但未传入,这会导致运行时错误,必须将res作为参数传入handleProcessError。
  3. 保留状态判断:responseAlreadySent的逻辑依然保留,防止其他未预见的场景下重复发送响应。

额外注意事项

  • 如果代码中还有其他触发sendResponse的逻辑,确保所有调用都遵循“先清定时器,再处理响应”的顺序。
  • JS的单线程特性保证了sendResponse的执行是串行的,不会出现responseAlreadySent状态判断的竞态问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:28:10