如何周期性同步检查请求状态并等待任务完成?解决setInterval未执行问题
问题分析与解决方案
首先,你的代码里有几个关键问题导致setInterval内的逻辑没按预期执行:
- 错误使用
await setInterval:setInterval返回的是一个数值类型的定时器ID,并不是Promise,所以await在这里完全不起作用,不会等待定时器执行。 - 未处理异步函数的返回值:
checkState是异步函数,你直接调用let state = checkState(exportId)得到的是一个Promise对象,不是实际的状态值,所以state !== '100%'永远为真,也永远不会触发clearInterval。 - 重复调用
checkState无意义:即使加了await,你连续两次调用checkState会发起两次重复请求,完全没必要。
正确的实现方式:用async/await循环替代setInterval
因为我们需要等待每次状态查询完成后,再等待20秒进行下一次查询,用while循环结合setTimeout的Promise封装会更可靠,也更容易理解和调试。
下面是修改后的完整代码:
// 先封装一个等待指定时间的工具函数 const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); async function waitForProcessCompletion(exportId: string) { // 先发起启动进程的请求(这里假设你已经有这部分代码) await startSlowProcess(exportId); while (true) { // 等待状态查询结果 const state = await checkState(exportId); console.log(`当前进程状态:${state}`); if (state === '100%') { console.log('进程已完成,继续执行主线程逻辑'); break; // 退出循环,继续后续逻辑 } // 状态未完成,等待20秒后再查询 await wait(20000); } // 这里写进程完成后的主线程逻辑 console.log('开始执行主线程后续操作'); } // 调用这个函数启动整个流程 waitForProcessCompletion('你的exportId'); // 你的checkState函数保持不变 const checkState = async (exportId: string): Promise<IStatus> => { const headers = {...}; const query = JSON.stringify({...}); const { _, data } = await axios.post(...); return data; };
代码解释:
wait工具函数:把setTimeout封装成Promise,这样可以用await来等待指定时间,比setInterval更适合异步流程控制。while(true)循环:持续查询状态,直到返回100%才退出循环。- 每次查询后等待:只有当状态查询完成(不管成功还是失败,这里可以根据需要加错误处理),才会等待20秒进行下一次查询,避免了
setInterval可能导致的并发请求问题。 - 错误处理建议:你可以在
checkState的调用处加上try/catch,处理请求失败的情况,比如网络错误时重试,避免整个流程崩溃:
while (true) { try { const state = await checkState(exportId); console.log(`当前进程状态:${state}`); if (state === '100%') { console.log('进程已完成,继续执行主线程逻辑'); break; } } catch (error) { console.error('状态查询失败,稍后重试:', error); } await wait(20000); }
这种方式比setInterval更可控,能更好地处理异步操作的顺序和错误,确保主线程在进程完成后才继续执行后续逻辑。
内容的提问来源于stack exchange,提问作者Tlaloc-ES
相关产品推荐
相关产品推荐

