まだ手書きで setTimeout の Promise ラッパーを書いてるの?
// 默认分类 · 2026-05-19 · 阅读 3 分钟 · 53 次阅读
プロジェクトのどこかに、ほぼ確実にこれが潜んでる:
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 を立てるほどのことではない。