Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/427.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setImmediate vs.nextTick_Javascript_Node.js_Setimmediate - Fatal编程技术网

Javascript setImmediate vs.nextTick

Javascript setImmediate vs.nextTick,javascript,node.js,setimmediate,Javascript,Node.js,Setimmediate,Node.js版本0.10今天发布,并引入了setImmediate。文档建议在执行递归nextTick调用时使用它 从它看起来非常类似于进程.nextTick 如果要在事件队列中已存在的任何I/O事件回调之后对函数进行排队,我应该在何时使用下一个回调以及何时使用setImmediate?使用setImmediate。使用process.nextTick将函数有效地排在事件队列的最前面,以便在当前函数完成后立即执行 因此,如果您试图使用递归分解一个长时间运行、CPU受限的作业,现在,您可能希望使

Node.js版本0.10今天发布,并引入了
setImmediate
。文档建议在执行递归
nextTick
调用时使用它

从它看起来非常类似于
进程.nextTick


如果要在事件队列中已存在的任何I/O事件回调之后对函数进行排队,我应该在何时使用下一个回调以及何时使用setImmediate?

使用
setImmediate
。使用
process.nextTick
将函数有效地排在事件队列的最前面,以便在当前函数完成后立即执行


因此,如果您试图使用递归分解一个长时间运行、CPU受限的作业,现在,您可能希望使用
setImmediate
而不是
process.nextTick
对下一次迭代进行排队,否则任何I/O事件回调都无法在迭代之间运行。

如果您希望在事件中已经存在的任何I/O事件回调之后对函数进行排队,请使用
setImmediate
队列使用
process.nextTick
将函数有效地排在事件队列的最前面,以便在当前函数完成后立即执行


因此,如果您试图使用递归分解一个长时间运行、CPU受限的作业,您现在可能希望使用
setImmediate
而不是
process.nextTick
对下一次迭代进行排队,否则任何I/O事件回调都无法在两次迭代之间运行。

在回答中的注释中,它没有明确说明nextTick从宏观语义转移到微观语义

在节点0.9之前(当引入setImmediate时),nextTick在下一个调用堆栈的开始处运行

从节点0.9开始,nextTick在现有调用堆栈的末尾运行,而setImmediate在下一个调用堆栈的开头


查看工具和详细信息

在回答中的注释中,没有明确说明nextTick从宏观语义转换为微观语义

在节点0.9之前(当引入setImmediate时),nextTick在下一个调用堆栈的开始处运行

从节点0.9开始,nextTick在现有调用堆栈的末尾运行,而setImmediate在下一个调用堆栈的开头

查看工具和详细信息,如图所示

import fs from 'fs';
import http from 'http';

const options = {
  host: 'www.stackoverflow.com',
  port: 80,
  path: '/index.html'
};

describe('deferredExecution', () => {
  it('deferredExecution', (done) => {
    console.log('Start');
    setTimeout(() => console.log('TO1'), 0);
    setImmediate(() => console.log('IM1'));
    process.nextTick(() => console.log('NT1'));
    setImmediate(() => console.log('IM2'));
    process.nextTick(() => console.log('NT2'));
    http.get(options, () => console.log('IO1'));
    fs.readdir(process.cwd(), () => console.log('IO2'));
    setImmediate(() => console.log('IM3'));
    process.nextTick(() => console.log('NT3'));
    setImmediate(() => console.log('IM4'));
    fs.readdir(process.cwd(), () => console.log('IO3'));
    console.log('Done');
    setTimeout(done, 1500);
  });
});
将给出以下输出

Start
Done
NT1
NT2
NT3
TO1
IO2
IO3
IM1
IM2
IM3
IM4
IO1
我希望这有助于理解两者的区别

更新:

使用
process.nextTick()
延迟的回调在任何其他I/O之前运行 事件被激发,而使用setImmediate()时,执行将排队 在队列中已存在的任何I/O事件之后

Node.js设计模式,由Mario Casciaro编写(可能是关于Node.js/js的最佳书籍)

举例说明

import fs from 'fs';
import http from 'http';

const options = {
  host: 'www.stackoverflow.com',
  port: 80,
  path: '/index.html'
};

describe('deferredExecution', () => {
  it('deferredExecution', (done) => {
    console.log('Start');
    setTimeout(() => console.log('TO1'), 0);
    setImmediate(() => console.log('IM1'));
    process.nextTick(() => console.log('NT1'));
    setImmediate(() => console.log('IM2'));
    process.nextTick(() => console.log('NT2'));
    http.get(options, () => console.log('IO1'));
    fs.readdir(process.cwd(), () => console.log('IO2'));
    setImmediate(() => console.log('IM3'));
    process.nextTick(() => console.log('NT3'));
    setImmediate(() => console.log('IM4'));
    fs.readdir(process.cwd(), () => console.log('IO3'));
    console.log('Done');
    setTimeout(done, 1500);
  });
});
将给出以下输出

Start
Done
NT1
NT2
NT3
TO1
IO2
IO3
IM1
IM2
IM3
IM4
IO1
我希望这有助于理解两者的区别

更新:

使用
process.nextTick()
延迟的回调在任何其他I/O之前运行 事件被激发,而使用setImmediate()时,执行将排队 在队列中已存在的任何I/O事件之后

Node.js设计模式,由Mario Casciaro编写(可能是关于Node.js/js的最佳书籍)


我想我可以很好地说明这一点。由于在当前操作结束时调用了
nextTick
,因此递归调用它可能会阻止事件循环继续
setImmediate
通过在事件循环的检查阶段触发来解决此问题,允许事件循环正常继续

   ┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
假设我们刚刚运行了这个程序,正在逐步完成事件循环的第一次迭代。它将调用迭代为零的
步骤
函数。然后它将注册两个处理程序,一个用于
setImmediate
,另一个用于
process.nextTick
。然后,我们从
setImmediate
处理程序递归调用该函数,该处理程序将在下一个检查阶段运行。
nextTick
处理程序将在中断事件循环的当前操作结束时运行,因此,即使它是第二次注册,它实际上也将首先运行

顺序是:
nextTick
在当前操作结束时激发,下一个事件循环开始,正常事件循环阶段执行,
setImmediate
激发并递归调用我们的
step
函数重新启动流程。当前操作结束,
nextTick
点火等

上述代码的输出为:

nextTick iteration: 0
setImmediate iteration: 0
nextTick iteration: 1
setImmediate iteration: 1
nextTick iteration: 2
setImmediate iteration: 2
nextTick iteration: 3
setImmediate iteration: 3
nextTick iteration: 4
setImmediate iteration: 4
nextTick iteration: 5
setImmediate iteration: 5
nextTick iteration: 6
setImmediate iteration: 6
nextTick iteration: 7
setImmediate iteration: 7
nextTick iteration: 8
setImmediate iteration: 8
nextTick iteration: 9
setImmediate iteration: 9
现在,让我们将对
step
的递归调用移到
nextTick
处理程序中,而不是
setImmediate

function step(iteration) {
  if (iteration === 10) return;
  setImmediate(() => {
    console.log(`setImmediate iteration: ${iteration}`);
  });
  process.nextTick(() => {
    console.log(`nextTick iteration: ${iteration}`);
    step(iteration + 1); // Recursive call from nextTick handler.
  });
}
step(0);
现在,我们已经将对
步骤
的递归调用移动到
nextTick
处理程序中,事情将以不同的顺序运行。事件循环的第一次迭代运行并调用
step
注册
setimmdaite
处理程序以及
nextTick
处理程序。当前操作结束后,我们的
nextTick
处理程序将触发,该处理程序递归调用
step
,并注册另一个
setImmediate
处理程序以及另一个
nextTick
处理程序。由于
nextTick
处理程序在当前操作后激发,因此在
nextTick
处理程序中注册
nextTick
处理程序将导致第二个处理程序在当前处理程序操作完成后立即运行。
nextTick
处理程序将继续启动,阻止当前事件循环继续。在看到单个
setImmediate
处理程序触发之前,我们将完成所有
nextTick
处理程序

上述代码的输出结果是:

nextTick iteration: 0
nextTick iteration: 1
nextTick iteration: 2
nextTick iteration: 3
nextTick iteration: 4
nextTick iteration: 5
nextTick iteration: 6
nextTick iteration: 7
nextTick iteration: 8
nextTick iteration: 9
setImmediate iteration: 0
setImmediate iteration: 1
setImmediate iteration: 2
setImmediate iteration: 3
setImmediate iteration: 4
setImmediate iteration: 5
setImmediate iteration: 6
setImmediate iteration: 7
setImmediate iteration: 8
setImmediate iteration: 9
请注意,如果我们没有中断递归调用并在10次迭代后中止它,
nextTick
调用将继续重复
Promise.resolve().then(() => { console.log('this happens FIRST'); });

setImmediate(() => {
  console.log('this happens LAST');
})
const nt_recursive = () => process.nextTick(nt_recursive);
nt_recursive(); // setInterval will never run

const si_recursive = () => setImmediate(si_recursive);
si_recursive(); // setInterval will run

setInterval(() => console.log('hi'), 10);
function foo(count, callback) {
  if (count <= 0) {
    return process.nextTick(() => callback(new TypeError('count > 0')));
  }
  myAsyncOperation(count, callback);
}