Node js的回调队列排序

时间:2018-07-27 18:14:30

标签: node.js

示例1:

console.log('Starting app');

setTimeout(() => {
  console.log('callback 1');
}, 2000);

sleep(4000);

setTimeout(() => {
  console.log('callback 2');
}, 1000);

console.log('Finishing up');

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

//Its Output
Starting app
Finishing up
Callback 1
Callback 2

示例2:

console.log('Starting app');

setTimeout(() => {
  console.log('callback 1');
}, 2000);

sleep(4000);

setTimeout(() => {
  console.log('Callback 2');
}, 0);

console.log('Finishing up');

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

//Its Output
Starting app
Finishing up
Callback 2
Callback 1

我试图了解两个异步函数计时器开始同时执行或一个接一个地执行。
Example 1工作正常。回调1首先到达队列,因为它的超时时间为2秒。因为在回调2之前有4秒钟的延迟。

Example 2此示例无法正常工作。应该先在队列中到达回调1,因为它的超时为2秒,延迟为回调2前的4秒。

1 个答案:

答案 0 :(得分:1)

似乎假设sleep函数的循环可能不会在超时之前完成。

console.log('Starting app');

sleep(4000);

console.log('Finishing app');

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      console.log('breaking');
      break;
    }
  }

  console.log(`Sleep time: ${new Date().getTime() - start}ms`);
}

完成循环的时间取决于运行的计算机,但是大多数现代计算机都不会中断,因为它完成的时间比分配的时间快。这会产生一定范围的“睡眠”时间,这可能导致在不同的机器上获得不同的输出(如果增量足够小,则两次运行之间在同一台机器上甚至会有不同的输出)。

例如,在我的一台机器上,此代码完成需要大约800毫秒(750毫秒至830毫秒的范围)。比指定的4000毫秒短得多。

因此,在第一个测试示例中,代码将在我的计算机上运行:

  • 设置输出“回调1”的超时时间为2000ms
  • 循环约800毫秒(不需要4000毫秒)
  • 设置输出“回调2”的超时时间为1000ms

这导致“回调2”在约1800ms处打印,而“回调1”在约2000ms处打印。考虑到它们之间的距离,我敢冒险您正在使用的机器执行该循环要慢一些,因此您可以按照指示的方式观察它。

在第二个测试示例中,代码将在我的计算机上这样执行:

  • 设置输出“回调1”的超时时间为2000ms
  • 循环约800毫秒(不需要4000毫秒)
  • 将输出“回调2”设置为0ms超时

这导致“回调2”在〜800ms处打印,而“回调1”在〜2000ms处打印。由于您的计算机速度足够快,可以在4秒内完成循环,因此您现在可以观察到问题中指出的“意外”输出。

因此,基本上,您用来“睡眠”的循环并没有提供您基于期望的等待时间。