93

nextTick と setImmediate の違いについて非常に混乱しています。インターネットでそれらに関するすべてのドキュメントを読みましたが、それらがどのように機能するかはまだわかりません。

例:

function log(n) { console.log(n); }

setImmediate

setImmediate(function() {
  setImmediate(function() {
    log(1);
    setImmediate(function() { log(2); });
    setImmediate(function() { log(3); });
  });
  setImmediate(function() {
    log(4);
    setImmediate(function() { log(5); });
    setImmediate(function() { log(6); });
  });
});

//1 2 3 4 5 6

次のティック

process.nextTick(function() {
  process.nextTick(function() {
    log(1);
    process.nextTick(function() { log(2); });
    process.nextTick(function() { log(3); });
  });
  process.nextTick(function() {
    log(4);
    process.nextTick(function() { log(5); });
    process.nextTick(function() { log(6); });
  });
});

//1 4 2 3 5 6

これらの結果はなぜですか?視覚的または非常にわかりやすい説明で説明してください。ノードのコア開発者でさえ、人々が nextTick と setImmediate をどのように理解すべきかについて同意していません。

ソース:

4

5 に答える 5

106

次の 2 つの例を考えてみましょう。

setImmediate

setImmediate(function A() {
  setImmediate(function B() {
    log(1);
    setImmediate(function D() { log(2); });
    setImmediate(function E() { log(3); });
  });
  setImmediate(function C() {
    log(4);
    setImmediate(function F() { log(5); });
    setImmediate(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 'TIMEOUT FIRED' 1 4 2 3 5 6
// OR
// 1 'TIMEOUT FIRED' 4 2 3 5 6

次のティック

process.nextTick(function A() {
  process.nextTick(function B() {
    log(1);
    process.nextTick(function D() { log(2); });
    process.nextTick(function E() { log(3); });
  });
  process.nextTick(function C() {
    log(4);
    process.nextTick(function F() { log(5); });
    process.nextTick(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 1 4 2 3 5 6 'TIMEOUT FIRED'

setImmediate コールバックは、キューに入れられた順序で反復ごとに 1 回、イベント ループから起動されます。したがって、イベント ループの最初の繰り返しで、コールバック A が起動されます。次に、イベント ループの 2 回目の繰り返しでコールバック B が起動され、イベント ループの 3 回目の繰り返しでコールバック C が起動されます。これにより、イベント ループがブロックされるのを防ぎ、他の I/O またはタイマー コールバックを実行できるようになります。その間に呼び出されます (1 回目または 2 回目のループ反復で発生する 0ms タイムアウトの場合と同様)。

ただし、nextTick コールバックは常に、現在のコードの実行が完了した直後で、イベント ループに戻る前に発生します。nextTick の例では、イベント ループに戻る前にすべての nextTick コールバックを実行することになります。setTimeout のコールバックはイベント ループから呼び出されるため、すべての nextTick コールバックが完了するまで、テキスト 'TIMEOUT FIRED' は出力されません。

于 2013-11-30T04:37:40.970 に答える
8

の結果を再現できませんsetImmediatenextTickこの状況では、ほとんど同じことを行うため、(私のテストではそうです) と同じである必要があります。それについての唯一の合理的な説明は、setImmediate何らかの形で同期しているということですが、そうではありません。

そして、NodeJS のドキュメントによると、唯一の本当の違いは、複数nextTickが 1 回のループ反復で発火する可能性があること (に応じてmaxTickDepth)、setImmediate反復ごとに 1 回発火することです。

于 2013-07-06T13:18:49.340 に答える