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

Rah*_*ran 9 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"));
Run Code Online (Sandbox Code Playgroud)

运行上面代码的输出是

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
Run Code Online (Sandbox Code Playgroud)

现在我在"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")();
Run Code Online (Sandbox Code Playgroud)

运行上面的代码后,输出是

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
Run Code Online (Sandbox Code Playgroud)

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

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

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

那么它与我的第二种方法有什么不同呢?

请解释一下或给我一些指示

Siv*_*nan 6

首先让我们了解 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);
}
Run Code Online (Sandbox Code Playgroud)
const maybeTrue = Math.random() > 0.5;

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

bar();
Run Code Online (Sandbox Code Playgroud)

目前尚不清楚是否foo()bar()将首先被调用。下面的方法要好得多:

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

  fs.stat('file', cb);
}
Run Code Online (Sandbox Code Playgroud)

@Johannes Merz 在他的回答中已经提到了为什么使用它process.nextTick(callback)比使用它更好setTimeout(callback, 0)

更多信息请参考这里


Joh*_*erz 5

节点文档实际上很好地解释了何时以及为什么使用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()
Run Code Online (Sandbox Code Playgroud)


AJS*_*AJS 3

您在帖子中找到了答案,您在帖子中与我们分享了您的成果:

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

结果

Next TICK ONE, 
Next TICK TWO, 
Next TICK THREE, 
Next TICK FOUR, 
TIMEOUT AFTER-ONE
TIMEOUT AFTER-TWO
TIMEOUT AFTER-THREE
Run Code Online (Sandbox Code Playgroud)

当您使用时,process.nextTick您基本上确保您作为参数传递的函数将在下一个tick中立即调用,即。下一个事件循环的开始。这就是为什么下一个tick中的所有函数都会在计时器之前执行,即。setTimeout下一个刻度并不意味着下一秒,它意味着 Nodejs 事件循环的下一个循环。另外,下一个刻度确保您尝试调用的函数是异步执行的。下一个时钟周期的优先级高于在事件循环中排队等待执行的计时器、I/O 操作等。当您想要确保代码在下一个事件循环中而不是在指定时间之后执行时,您应该使用 nextTick。nextTick 比计时器更高效,并且当您想确保您调用的函数异步执行时。您可以在 Nodejs文档中找到更多相关信息

  • 我认为“[...]将在下一个tick中立即调用,即下一个事件循环的开始[...]”(和其他)有点误导。事件循环由几个阶段组成,process.nextTick 不会在下一个循环开始时开始,而是在当前操作之后立即开始 (4认同)