簡體   English   中英

為什么process.nextTick()會在此“偽異步函數”中觸發TypeError,而setTimeout()不會呢?

[英]Why does process.nextTick() trigger a TypeError in this “fake asynchronous function”, but setTimeout() doesn't?

注意:我在Node.js上運行了這段代碼

我正在制作一個假的“非阻塞”函數,所以我可以理解如何為Node.js編寫異步函數。 這樣做的時候,我遇到了一個我不太了解的場景。

下面有一個“假”異步函數的代碼,該函數帶有一個回調函數和一個計數器。 該函數將遞歸調用自身[counter]次,然后執行提供的回調函數。 每10次迭代,它將控制權釋放回事件隊列。

原始劇本

//fakeCounter helps us keep track of whether or not the operation is "complete"
//fn is the callback function that will be executed when the operation is complete
function asyncOp(fn, fakeCounter){
  //if fakeCounter is less than or equal to zero, that means the
  //operation is "complete" and you can call the callback now
  if(fakeCounter <= 0) return fn();

  console.log("another [" + fakeCounter + "] cycles to go");

  //every 10 or so iterations, release control
  if(fakeCounter % 10 === 0){
    process.nextTick(asyncOp(fn,--fakeCounter));
  }else{
    asyncOp(fn,--fakeCounter);
  }
}


asyncOp(function (){
  console.log("operation complete");
}, 10000);

如上所示,我可以通過使用process.nextTick來釋放控件。 但是,當我執行腳本時,出現以下錯誤:

原始結果

  another [10000] cycles to go
  another [9999] cycles to go
  another [9989] cycles to go
  ...
  another [3] cycles to go
  another [2] cycles to go
  another [1] cycles to go
  operation complete

  node.js:415
            callback();
            ^
  TypeError: undefined is not a function
    at process._tickCallback (node.js:415:13)
    at Function.Module.runMain (module.js:499:11)
    at startup (node.js:119:16)
    at node.js:902:3

此錯誤和堆棧跟蹤對我來說幾乎沒有意義,因此我被撓了一下頭。

但是,當我修改asyncOp函數以使其通過setTimeout釋放控制權時,不會出現此類錯誤:

修改功能

function asyncOp(fn, fakeCounter){
  if(fakeCounter <= 0) return fn();

  console.log("another [" + fakeCounter + "] cycles to go");

  if(fakeCounter % 10 === 0){
    setTimeout(asyncOp(fn, --fakeCounter)); //<-- see here
  }else{
    asyncOp(fn,--fakeCounter);
  }
}

修改結果

  ...
  another [3] cycles to go
  another [2] cycles to go
  another [1] cycles to go
  operation complete

而且沒有任何錯誤發生。

...因此,我的問題是:為什么使用process.nextTick()引發TypeError,而使用setTimeout()卻沒有呢? 為什么首先要引發TypeError?

編輯:

如果將來有人在讀這個,正確的答案(如下面提到的@ m02ph3u5)是將函數調用包裝在匿名函數中:

if(fakeCounter % 10 === 0){
   process.nextTick(function(){asyncOp(fn, --fakeCounter)}). 
}else{
   asyncOp(fn,--fakeCounter);
}

但是,在此特定示例中,最好使用setImmediate而不是process.nextTick,因為顯然遞歸的process.nextTick調用將在下一版本的node.js中中斷。 此外,在這種情況下使用process.nextTick()將導致RangeError。 因此,正確的解決方案是使用以下方法:

if(fakeCounter % 10 === 0){
    setImmediate(function (){
       asyncOp(fn,--fakeCounter)
    });
}else{
    asyncOp(fn,--fakeCounter);
}

謝謝@ m02ph3u5和@mscdex

原因是process.nextTick()期望將函數作為第一個參數,而asyncOp()返回undefined (默認情況下)。 undefined不是一個函數,因此會引發TypeError setTimeout()當前不會立即檢查其第一個參數的類型(但是這將在節點v6中更改),因此這就是它不會引發錯誤的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM