記事タイトルの通り、JavaScript という非同期な世界で sleep する方法を考えてみます。もちろん、寝たいわけではなくて、待たせたいわけですよ。なので、wait させたい、とも言えますね。
旧来より JavaScript の世界で指定秒数だけ待たせたい場合は setTimeout()
を使ってきました。しかし非同期の処理をシーケンシャルに実行しなければならないシーンが増えた近年では、setTimeout()
のコールバック関数方式ではコードの見通しが悪く、できる限り使いたくないというのが本音です。なのでここでは Promise
や async/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 の Promise
版 setTimeout()
が欲しいですよね。これはどの団体が策定するのでしょうね。JavaScript のタイマー関数は window
オブジェクトのメソッドなので Ecma International ではなさそう。WHATWG かな?
今回は以上で終わりです。最後まで読んでくださりありがとうございました。それでは次回の記事までごきげんよう。