はじめに
先日(2021/6/28)、「Node学園 36時限目 オンライン」というイベントで「Node16の新機能の紹介」という内容で発表させて頂きました。(視聴&リアクションくださった方々、ありがとうございました)
その中の発表資料でSleep機能(C#やJavaのThread.sleep()みたいな機能)のコードを書いていたのですが、発表後のトーク&Twitterで「Node.js16から、Sleep機能がCore機能でサポートされたんですよ」ということを教えて頂きました。
それは知らなかった!ということで、Node.js16でのSleep機能をさっそく試してみました。
Node.jsでのSleep機能について
Sleep機能について、Node.js14まではCore APIでのサポートがなかったため、下記の方法で代用する必要がありました。
- コードで代替(setTimeOut関数を使用、下記ソース参照)
- 各種npmモジュールを使用する
// Sleep処理を実行するコード const _sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function main() { // 指定したミリ秒数、処理をSleepする。 await _sleep(1000); }
しかし、Node.js16から「Timers Promiss API」が使えるようになり(※)、これを使うことで、代替コードを書くことなしでSleep機能を使用することができます。
※ 正確には、Node.js15でExperimentalとして追加されたものが、Node.js16でStableになった
実際実装してみる
では、実際にSleep機能を実装してみます。
Timers Promise APIは「timers/promises」をimport(またはrequire)することで使用できます。
また、実際のSleep機能はTimers Promise APIの「setTimeout」関数を使用することで実現できます。(結果として、setTimeout関数を使うのは同じ)
参考:https://nodejs.org/dist/latest-v16.x/docs/api/timers.html#timers_timers_promises_api
async function main() { // const { setTimeout: sleep } = require('timers/promises'); const { setTimeout } = require('timers/promises'); // 指定したミリ秒数、処理をSleepする。 // Timers Promise APIのsetTimeOut関数だけで実装できるので、 // 独自コードは不要になった。 const before = Date.now(); await setTimeout(3000); const after = Date.now(); // 大体3000くらいの値になる。 console.log(`経過時間:${after - before}`); }
なお、エイリアスをつけておけば、従来のsetTimeout関数との併用もできます。
const { setTimeout: sleep } = require('timers/promises'); const _sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function main() { // timers/promisesのsetTimeout関数と従来のsetTimeout関数を併用する。 const before = Date.now(); await sleep(3000); await _sleep(5000); const after = Date.now(); // 大体8000くらいの値になる。 console.log(`経過時間:${after - before}`); }
setTimeout以外の関数
setTimeout以外にも、タイマー系関数の「setInterval, setImmediate」もTimers Promise APIでサポートされています。
※ただsetImmediateは、正直Timers Promise APIでの用途がいまいちわかっていない...コールバック関数の実行ならわかるんだけど、戻り値を返すって、どういう用途に使うんだろうか?
const { setInterval, setImmediate } = require('timers/promises'); async function main() { // timers/promisesのsetIntervalを使用する。 console.log('timerPromise started'); const iterators = setInterval(1000); let cnt = 0; for await (const iterator of iterators) { cnt++; console.log(`${cnt.toString()} 回目の実行`); if (5 <= cnt) break; } // timers/promisesのsetImmediateを使用する。 const res = await setImmediate("immediate!"); console.log(`res is ${res}`); }
結果:
まとめ
Sleep機能を始め、setIntervalのpromiseを公式がサポートしてくれたのは良いなあと思いました。
ていうか、もっといろいろとチェックしておかないとなあ、とも感じました。
それでは、今回はこの辺で。