为什么以及何时使用process.nextTick?

时间:2016-11-16 10:15:46

标签: javascript node.js

以下是“practise01.js”文件中的代码,

function fn(name){
   return f;

   function f(){
       var n = name;
       console.log("Next TICK "+n+", ");        
   }
}

function myTimeout(time,msg){
   setTimeout(function(){
       console.log("TIMEOUT "+msg);
   },time); 
}

process.nextTick(fn("ONE"));
myTimeout(500,"AFTER-ONE");
process.nextTick(fn("TWO"));
myTimeout(500,"AFTER-TWO");
process.nextTick(fn("THREE"));
myTimeout(500,"AFTER-THREE");
process.nextTick(fn("FOUR"));

运行上面代码的输出是

rahul@rahul:~/myPractise/PlainNodeJSPractise01/Process$ node practise01.js                  

Next TICK ONE, 
Next TICK TWO, 
Next TICK THREE, 
Next TICK FOUR, 
TIMEOUT AFTER-ONE
TIMEOUT AFTER-TWO
TIMEOUT AFTER-THREE

现在我在“practise02.js”中使用process.nextTick编写代码,如下所示,

function myTimeout(time,msg){
  setTimeout(function(){
        console.log("TIMEOUT "+msg);
  },time);  
}

function fn(name){
  return f;

  function f(){
    var n = name;
    console.log("Next TICK "+n+", ");       
  }
}

fn("ONE")();
myTimeout(500,"AFTER-ONE");
fn("TWO")();
myTimeout(500,"AFTER-TWO");
fn("THREE")();
myTimeout(500,"AFTER-THREE");
fn("FOUR")();

运行上面的代码后输出

rahul@rahul:~/myPractise/PlainNodeJSPractise01/Process$ node practise02.js 
Next TICK ONE, 
Next TICK TWO, 
Next TICK THREE, 
Next TICK FOUR, 
TIMEOUT AFTER-ONE
TIMEOUT AFTER-TWO
TIMEOUT AFTER-THREE

如果您看到两个输出都相同。

所以在这种情况下我需要使用process.nextTick?

当我尝试阅读更多内容时,我理解的是如果我需要在eventloop为空时立即执行某个函数而不是去“process.nextTick”。

那么它与我的第二种方法有何不同。

请解释我或给我一些指示

3 个答案:

答案 0 :(得分:4)

节点文档实际上非常适合解释使用nextTick的时间和原因:

https://nodejs.org/api/process.html#process_process_nexttick_callback_args

它的作用:

  

这不是setTimeout(fn,0)的简单别名,它效率更高。它在事件循环的后续滴答中触发任何其他I / O事件(包括定时器)之前运行。

以及何时使用:

  

这在开发API时很重要,以便在构造对象之后但在任何I / O发生之前为用户提供分配事件处理程序的机会......

function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }

  fs.stat('file', cb);
}
definitelyAsync(true, () => {
  foo();
});
bar(); // will now allways be called before foo()

答案 1 :(得分:1)

您在自己的帖子中得到了答案:

rahul@rahul:~/myPractise/PlainNodeJSPractise01/Process$ node practise02.js 
Next TICK ONE, 
Next TICK TWO, 
Next TICK THREE, 
Next TICK FOUR, 
TIMEOUT AFTER-ONE
TIMEOUT AFTER-TWO
TIMEOUT AFTER-THRE

如果我们将超时间隔从500更改为0仍然是相同的结果:

function fn(name){
   return f;

   function f(){
       var n = name;
       console.log("Next TICK "+n+", ");
   }
}

function myTimeout(time,msg){
   setTimeout(function(){
       console.log("TIMEOUT "+msg);
   },time);
}

process.nextTick(fn("ONE"));
myTimeout(0,"AFTER-ONE");// set timeout to execute in 0 seconds for all
process.nextTick(fn("TWO"));
myTimeout(0,"AFTER-TWO");
process.nextTick(fn("THREE"));
myTimeout(0,"AFTER-THREE");
process.nextTick(fn("FOUR"));

<强>结果

Next TICK ONE, 
Next TICK TWO, 
Next TICK THREE, 
Next TICK FOUR, 
TIMEOUT AFTER-ONE
TIMEOUT AFTER-TWO
TIMEOUT AFTER-THREE

当你使用process.nextTick时,你基本上确保你作为参数传递的函数将在下一个tick中被立即调用,即。下一个事件循环的开始。这就是为什么你的下一个tick中的所有函数都在你的计时器之前执行,即。 setTimeout下一个tick并不意味着下一秒它意味着nodejs eventloop的下一个循环。另外,下一个tick会确保您尝试调用的函数是异步执行的。并且下一个tick的优先级高于您的计时器,I / O操作等在事件循环中排队等待执行。如果要确保在下一个事件循环中而不是在指定时间之后执行代码,则应使用nextTick。 nextTick比定时器更有效,当你想确保你调用的函数是异步执行的。您可以在nodejs docs

中找到有关此内容的更多信息

答案 2 :(得分:0)

process.nextTick()的行为

Eventloop有多个阶段,每个阶段中都会执行不同类型的异步函数。

process.nextTick(callback[, ...args])是nodeJS异步API的一部分。但这从技术上讲不是事件循环的一部分。

nextTickQueue将在当前操作完成后处理,而不管事件循环的当前阶段如何。

每次在给定的事件循环阶段调用process.nextTick()时,传递给process.nextTick()的回调都会在事件循环继续之前得到解决。

为什么我们需要使用process.nextTick

对于API而言,100%同步或100%异步非常重要。考虑以下示例:

// WARNING!  DO NOT USE!  BAD UNSAFE HAZARD!
function maybeSync(arg, cb) {
  if (arg) {
    cb();
    return;
  }

  fs.stat('file', cb);
}
const maybeTrue = Math.random() > 0.5;

maybeSync(maybeTrue, () => {
  foo();
});

bar();

尚不清楚将首先调用foo()还是bar()。 以下方法更好:

function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }

  fs.stat('file', cb);
}

@Johannes Merz已经在回答中提到了为什么使用process.nextTick(callback)而不是setTimeout(callback, 0)

很好

有关更多信息,请参见here