なっく日報

技術やら生活やらのメモ

process.nextTickとsetImmediateの違い

自分的な結論

パフォーマンス上の問題が起きない限りは、setImmediateを使っておくのが無難

process.nextTicksetImmediateの違い

jxck.hatenablog.com

が素晴らしくまとまっているので、詳しくはコチラの記事を読んでいただきたいのですが、

ポイントを。

コード

'use strict';
const fs = require('fs');

console.log('start');

fs.readFile('./a.txt', (err, data) => {
  console.log('readFile');

  process.nextTick(() => {
    console.log('readFile -> nextTick');
  });

  setImmediate(() => {
    console.log('readFile -> setImmediate');
  });
});

process.nextTick(() => {
  console.log('nextTick');
  fs.readFile('./a.txt', (err, data) => {
    console.log('nextTick -> readFile');
  });
});

setImmediate(() => {
  console.log('setImmediate');
  fs.readFile('./a.txt', (err, data) => {
    console.log('setImmediate -> readFile');
  });
});

(function doNextTick(i) {
  console.log(`doNextTick ${i}`);
  if (i >= 5) {
    return;
  }
  i++;
  process.nextTick(() => {
    doNextTick(i);
  });
})(1);

(function doSetImmediate(i) {
  console.log(`doSetImmediate ${i}`);
  if (i >= 5) {
    return;
  }
  i++;
  setImmediate(() => {
    doSetImmediate(i);
  });
})(1);

(function doNextTick2(i) {
  console.log(`doNextTick2 ${i}`);
  if (i >= 5) {
    return;
  }
  i++;
  process.nextTick(() => {
    doNextTick2(i);
  });
})(1);

実行結果

start
doNextTick 1
doSetImmediate 1
doNextTick2 1
nextTick
doNextTick 2
doNextTick2 2
doNextTick 3
doNextTick2 3
doNextTick 4
doNextTick2 4
doNextTick 5
doNextTick2 5
readFile
readFile -> nextTick
nextTick -> readFile
setImmediate
doSetImmediate 2
readFile -> setImmediate
setImmediate -> readFile
doSetImmediate 3
doSetImmediate 4
doSetImmediate 5

結果

  • 再帰関数である、doNextTickとdoNextTick2が終わるまでreadFileが呼び出されない。イベントループをブロックしてしまっている
  • setImmediateは↑のjxckさんの参考記事の図の通り、IOイベント終了後に呼び出されているよう。イベントループをブロックしていない

まとめ

この辺の挙動を知らないでprocess.nextTickを使うと痛い目にあう可能性があります。
きちんと用法用量を守って使う、自信なければsetImmediateにしといた方がいいというのが自分的な結論です