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

まだ手書きで 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 を立てるほどのことではない。

#Typescript