echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【Node.js】Node.js version16の新機能 その2(Sleep機能)

はじめに

先日(2021/6/28)、「Node学園 36時限目 オンライン」というイベントで「Node16の新機能の紹介」という内容で発表させて頂きました。(視聴&リアクションくださった方々、ありがとうございました)

nodejs.connpass.com

その中の発表資料で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}`);  
} 

結果:
f:id:Makky12:20210701101849p:plain

まとめ

Sleep機能を始め、setIntervalのpromiseを公式がサポートしてくれたのは良いなあと思いました。

ていうか、もっといろいろとチェックしておかないとなあ、とも感じました。

それでは、今回はこの辺で。