文章stop-writing-your-own-sleep-function.md

还在手写 setTimeout 的 Promise 包装?

// 默认分类 · 2026-05-19 · 阅读 2 分钟 · 52 次阅读

项目某个角落大概率藏着这个:

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

能跑,没错,不过 Node.js 16 开始其实自己就有了,在 timers/promises 里,直接拿来用就好。

import { setTimeout as sleep } from "node:timers/promises";

node: 前缀是为了明确告诉工具链这是内置模块,不是 node_modules 里某个撞名的包。as sleep 是因为叫 setTimeout 看着别扭,改个名更清晰。

基础用法

async function main() {
  await sleep(2000);
  console.log("等了 2 秒");
}

和手写版效果一样,但少了一个没必要存在的工具函数。

它比你手写的多一个参数

setTimeout(delay?: number, value?: T, options?: TimerOptions): Promise<T>

第二个参数 value 是 resolve 的时候顺便带出来的值,有时候挺方便的(有时候完全用不上,知道有就行)。

第三个参数 options 里有 signal,接 AbortController,可以中途取消等待,手写版要实现这个要麻烦不少。

const controller = new AbortController();
setTimeout(() => controller.abort(), 500);

try {
  await sleep(2000, undefined, { signal: controller.signal });
} catch (e) {
  console.log("取消了");
}

类型

@types/node 18 以上类型是完整的,泛型也对,不用手动标注。报错的话先查一下版本,大概率是 @types/node 太旧了,npm update @types/node 通常能解决。

旧项目怎么办

有就顺手换掉,没必要专门开 PR 做这件事。

#Typescript