Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.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 一直在理解节点js的异步行为_Javascript_Node.js_Asynchronous_Ecmascript 6 - Fatal编程技术网

Javascript 一直在理解节点js的异步行为

Javascript 一直在理解节点js的异步行为,javascript,node.js,asynchronous,ecmascript-6,Javascript,Node.js,Asynchronous,Ecmascript 6,我正在学习NodeJS回调和异步行为,从给出的示例中,我编写了以下代码来更好地理解它 function callbackTester (callbackFn){ console.log('From callback tester.'); callbackFn(); } function pollingWait(){ while (true) {} } callbackTester(() => { console.log('From anonymous f

我正在学习NodeJS回调和异步行为,从给出的示例中,我编写了以下代码来更好地理解它

function callbackTester (callbackFn){
    console.log('From callback tester.');
    callbackFn();
}

function pollingWait(){
    while (true) {}
}

callbackTester(() => {
    console.log('From anonymous function.');
    setTimeout(()=>{
        console.log("I'm waiting!");
    }, 500);
    // pollingWait();
});
console.log('I am the last one');
现在,当我注释掉
pollingWait()
函数时,它会按预期工作。它给出以下输出:

From callback tester.
From anonymous function.
I am the last one
I'm waiting!
现在,当我注释掉
setTimeout
函数并添加
pollingWait()
时,程序进入无限循环。我认为这也是一种预期的行为,因为节点js是单线程的,无法避免无限循环。那么,这种异步行为在幕后是如何工作的呢

它如何决定何时继续执行,何时不继续执行?有没有可能让我自己的函数像
setTimeout
那样起异步作用?

我认为这也是一种预期的行为,因为节点js是单线程的,无法避免无限循环

但是只有一个主线程,除非您创建辅助线程

那么,这种异步行为在幕后是如何工作的呢

Node.js的主线程在循环中工作:顶级代码运行并返回,然后任何排队操作(如计时器回调)运行并返回,然后下一个排队操作运行并返回,等等。这就是
setTimeout
的工作方式:当计时器启动时,事件循环会看到这一点,并将对计时器回调的调用排入队列。还要注意,虽然Node.js默认只有一个主JavaScript线程,但这并不意味着节点本身是单线程的。特别是,它可以在另一个内部线程上执行I/O处理

有没有可能让我自己的函数像setTimeout一样异步

只有使用已经提供异步行为的东西并包装它。这些措施包括:

  • setTimeout
  • setImmediate
  • process.nextTick
  • 承诺的
    然后
    捕获
    回调
乍一看,您可能会认为
async
函数可以做到这一点,但实际上它们没有做到:
async
函数中的代码一直同步运行,直到它第一次等待承诺解析(或者直到它返回)。因此,异步性实际上与上面最后一点相同:一个
然后
catch
回调

不能做的事情(没有工作线程)是忙等待,就像
轮询等待一样,因为在运行忙等待的线程上不会发生任何其他事情

我认为这也是一种预期的行为,因为节点js是单线程的,无法避免无限循环

但是只有一个主线程,除非您创建辅助线程

那么,这种异步行为在幕后是如何工作的呢

Node.js的主线程在循环中工作:顶级代码运行并返回,然后任何排队操作(如计时器回调)运行并返回,然后下一个排队操作运行并返回,等等。这就是
setTimeout
的工作方式:当计时器启动时,事件循环会看到这一点,并将对计时器回调的调用排入队列。还要注意,虽然Node.js默认只有一个主JavaScript线程,但这并不意味着节点本身是单线程的。特别是,它可以在另一个内部线程上执行I/O处理

有没有可能让我自己的函数像setTimeout一样异步

只有使用已经提供异步行为的东西并包装它。这些措施包括:

  • setTimeout
  • setImmediate
  • process.nextTick
  • 承诺的
    然后
    捕获
    回调
乍一看,您可能会认为
async
函数可以做到这一点,但实际上它们没有做到:
async
函数中的代码一直同步运行,直到它第一次等待承诺解析(或者直到它返回)。因此,异步性实际上与上面最后一点相同:一个
然后
catch
回调

如果没有工作线程,无法做的事情是忙等待,就像您的
轮询等待一样,因为在运行忙等待的线程上不会发生任何其他事情。

尝试以下方法:

let done = false;

setTimeout(() => {
  done = true
}, 5);

const eventLoopQueue = () => {
  return new Promise(resolve => 
    setImmediate(() => {
      console.log('event loop');
      resolve();
    })
  );
}

const run = async () => {
  while (!done) {
    console.log('loop');
    await eventLoopQueue();
  }
}

run().then(() => console.log('Done'));
试试这个:

let done = false;

setTimeout(() => {
  done = true
}, 5);

const eventLoopQueue = () => {
  return new Promise(resolve => 
    setImmediate(() => {
      console.log('event loop');
      resolve();
    })
  );
}

const run = async () => {
  while (!done) {
    console.log('loop');
    await eventLoopQueue();
  }
}

run().then(() => console.log('Done'));

关键词:事件循环JavaScriptOK谢谢。这回答了我的第一个问题。第二个呢?您可以在while(true){}循环中添加延迟,这会导致它跳出并偶尔处理其他事情。。。查看下面的视频了解Javascript事件循环工作解释关键字:事件循环javascriptOkay谢谢。这回答了我的第一个问题。第二个呢?您可以在while(true){}循环中添加延迟,这会导致它跳出并偶尔处理其他事情。。。查看下面的视频,了解Javascript事件循环工作解释完美!谢谢你的解释。太好了!谢谢你的解释。