setInterval等待时间是前次调用还是结束后计算?如何控制循环迭代间隔?
setInterval的执行逻辑
你写的setInterval写法不会等待上一次回调执行完成,它的计时起点是上一次回调被推入事件队列的时间,只要间隔时间到就会把下一次回调加入事件队列。
如果你的CallAPI是异步请求、或者回调内的处理逻辑耗时超过300ms,就会出现多个回调叠加执行的情况,请求并发数直接超出API的速率限制,甚至会因为事件队列积压,出现阻塞恢复后一次性触发大量请求的问题,完全不适合你的使用场景。
同步while循环套setTimeout的执行逻辑
这个写法存在严重问题:while(true)是同步死循环,会持续占用JS主线程,你注册的所有setTimeout回调根本没有机会被事件循环调度执行。
同时这个循环会在极短时间内创建成千上万的定时器,等到300ms计时结束后,所有回调会同时触发,瞬间发出的请求量会直接击穿API的限流阈值,完全不可用。
异步while循环+await的写法(优化后可用)
你写的第三个写法逻辑方向是对的,但原生setTimeout不返回Promise,直接await setTimeout()不会生效,你需要先封装一个Promise版本的延时函数:
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))
修正后的写法如下:
while(true) { await CallAPI(); // 需保证CallAPI返回Promise,才会等待请求完成 // 执行后续处理逻辑 await sleep(300); // 等待300ms再进入下一轮 }
这个写法的执行顺序是严格可控的:
- 先等待
CallAPI请求完成、且后续处理逻辑全部执行结束 - 再等待300ms延时结束
- 才会进入下一轮循环发起新的请求
不会出现请求重叠,两次请求的最小间隔固定,完全可以满足API速率限制的要求。
内容的提问来源于stack exchange,提问作者eliezra236
相关产品推荐
相关产品推荐

