Node.js 如何实现 sleep(等待)?

Node.js 没有内置 sleep 函数,用 Promise 包装 setTimeout 即可:await new Promise(r => setTimeout(r, 3000))。Node 15+ 可用 timers/promises 的 setTimeout。注意千万别用同步忙等阻塞事件循环。

最佳实践
Node.js 事件循环与异步任务示意

标准写法:Promise 包一层 setTimeout,然后 await 它。

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function example() {
  console.log('开始');
  await sleep(3000);   // 等 3 秒
  console.log('结束');
}

example();

这种等待是非阻塞的:等待期间事件循环照常处理其他请求,这是它和"同步 sleep"的本质区别。

更省事:Node 15+ 内置版

const { setTimeout: sleep } = require('timers/promises');

await sleep(3000);            // 等 3 秒
await sleep(1000, '返回值');  // 还支持第二个参数作为 resolve 的值

ESM:import { setTimeout as sleep } from 'timers/promises';

循环里逐个处理(常见真实需求)

for (const item of items) {
  await process(item);
  await sleep(500);   // 每个请求间隔 500ms,防止打爆下游 API
}

注意必须 for...of + await;forEach 里 await 不生效(见本系列《forEach 里能用 async/await 吗》)。

警告:别用忙等待

// ❌ 千万别这么写:忙等会把事件循环彻底卡死,整个服务无响应
function badSleep(ms) {
  const end = Date.now() + ms;
  while (Date.now() < end) {}
}

Node 是单线程事件循环,忙等期间所有请求都得不到处理。需要同步阻塞的场景(几乎没有),正确做法也是把任务挪到 worker_threads。

常见问题(FAQ)

Q:setTimeout 的计时不准怎么办?
setTimeout 保证"至少这么久",不保证精确——事件循环忙时会延后。setInterval 同样不能保证精确时刻;需按实际时间修正漂移,严格实时任务不能依赖普通 JavaScript 定时器。

Q:sleep 能中途取消吗?
timers/promises 的 setTimeout 支持 AbortSignal:await sleep(5000, null, { signal }),外部 controller.abort() 即取消。

Q:测试里怎么 mock 掉 sleep?
注入 sleep 函数作为依赖,测试中替换成立即 resolve 的桩;或用 fake timers(sinon / vitest 自带)。

参考资料

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台