【JavaScript】sleep/wait する方法

記事タイトルの通り、JavaScript という非同期な世界で sleep する方法を考えてみます。もちろん、寝たいわけではなくて、待たせたいわけですよ。なので、wait させたい、とも言えますね。

旧来より JavaScript の世界で指定秒数だけ待たせたい場合は setTimeout() を使ってきました。しかし非同期の処理をシーケンシャルに実行しなければならないシーンが増えた近年では、setTimeout() のコールバック関数方式ではコードの見通しが悪く、できる限り使いたくないというのが本音です。なのでここでは Promiseasync/await を使う前提で考えてみましょう。

ワンライナーで手っ取り早く

何度も wait させる必要はなく、一回だけ固定の秒数だけ待たせたいなら、ワンライナーで setTimeout()Promise 化して await するのが個人的には好きです。

(async () => {
  console.time('Waited for');
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.timeLog('Waited for'); // Waited for: 1002.3310546875 ms
})();

個人的にワンライナーはコードが読み取りにくいので好きではないのですが、この程度なら許容範囲かなと思い、使っています。

関数化で汎用性を

関数化すれば、待たせる部分のコードは短くなりますし、待たせる秒数をパラメーター化すれば汎用性も上がります。

(async () => {
  console.time('Waited for');
  await wait(1000);
  console.timeLog('Waited for'); // Waited for: 1007.2958984375 ms
})();

function wait(msec) {
  return new Promise(resolve => setTimeout(resolve, msec));
}

node.js なら Promise 版の setTimeout()

node v16 以降のバージョンであれば Promise 版の setTimeout() が用意されています。node v15 で実験的に実装され、node v16 以降で正式に利用可能になりました。

(async () => {
  console.time('Waited for');
  await setTimeout(1000);
  console.timeLog('Waited for'); // Waited for: 1.003s
})();

もちろん、setTimeout() だけでなく setInterval()setImmediate()Promise 化したものが用意されています。筆者はまだ仕事では node v16 の環境でコードを書いたことがないので、普段はまったく Promise 版の setTimeout() は使っていませんが、node v16 が普及したころには頻繁に使ってそうです。

まとめ

ブラウザー上の JavaScript でも、node の PromisesetTimeout() が欲しいですよね。これはどの団体が策定するのでしょうね。JavaScript のタイマー関数は window オブジェクトのメソッドなので Ecma International ではなさそう。WHATWG かな?

今回は以上で終わりです。最後まで読んでくださりありがとうございました。それでは次回の記事までごきげんよう。

Share