node.js如何调度异步和同步任务?



我知道node.js是如何异步执行代码的,而不会通过使用事件循环来调度异步任务来阻塞主线程的执行,但我不清楚主线程实际上是如何决定为异步执行留出一段代码的。

(基本上是什么表明这段代码应该异步执行而不是同步执行,有什么区别因素?)

还有,node提供的异步和同步api是什么?

你的假设是错误的

什么指示这段代码应该异步执行而不是同步执行

错误是认为一些代码异步执行。这不是真的。 Javascript(包括node.js)执行所有同步代码。您的代码中没有任何部分是异步执行的。

乍一看,这就是你问题的答案:没有异步代码执行这回事。

等等,什么?

但是所有异步的东西呢?

就像我说的,node.js(和javascript一般)执行所有代码同步。然而,javascript能够等待对于某些事件异步。没有异步代码执行,但是有异步等待。

代码执行和等待的区别是什么?

让我们看一个例子。为了清晰起见,我将使用一种虚构语言中的伪代码,以消除javascript语法中的任何混淆。假设我们想从一个文件中读取数据。这个伪语言同时支持同步和异步等待:

例二。同步等待驱动器从文件

返回字节
data = readSync('filename.txt');
// the line above will pause the execution of code until all the
// bytes have been read

Example2。异步等待驱动器从文件

返回字节
// Since it is asynchronous we don't want the read function to 
// pause the execution of code. Therefore we cannot return the
// data. We need a mechanism to accept the returned value.
// However, unlike javascript, this fake language does not support
// first-class functions. You cannot pass functions as arguments
// to other functions. However, like Java and C++ we can pass
// objects to functions
class MyFileReaderHandler inherits FileReaderHandler {
method callback (data) {
// process file data in here!
}
}
myHandler = new MyFileReaderHandler()
asyncRead('filename.txt', myHandler);
// The function above does not wait for the file read to complete
// but instead returns immediately and allows other code to execute.
// At some point in the future when it finishes reading all data
// it will call the myHandler.callback() function passing it the
// bytes form the file.

可以看到,异步I/O并不是javascript所特有的。它早在javascript之前就存在于c++中,甚至在处理文件I/O、网络I/O和GUI编程的C库中。事实上,它甚至在c语言之前就已经存在了。你可以在汇编语言中实现这种逻辑(事实上,人们就是这样设计操作系统的)。

javascript的特别之处在于,由于它的函数性质(一级函数),传递一些你想在将来执行的代码的语法更简单:

asyncRead('filename.txt', (data) => {
// process data in here
});

或者在现代javascript中甚至可以使其看起来像同步代码:

async function main () {
data = await asyncReadPromise('filename.txt');
}
main();

等待和执行代码的区别是什么?难道你不需要代码来检查事件吗?

实际上,您需要刚好0%的CPU时间来等待事件。您只需要执行一些代码来注册一些中断处理程序和CPU硬件(不是软件)将在中断发生时调用中断处理程序。所有的硬件都被设计为触发中断:键盘,硬盘,网卡,USB设备,PCI设备等。

磁盘和网络I/O甚至更高效,因为它们也使用DMA。这些是硬件内存读取/写入器,可以从一个地方复制大块(千字节/兆字节)的内存。硬盘)到另一个地方(例如。RAM)。CPU实际上只需要设置DMA控制器,然后可以自由地做其他事情。一旦DMA控制器完成传输,它将触发一个中断,该中断将执行一些设备驱动程序代码,这些代码将通知操作系统一些I/O事件已经完成,这将通知node.js执行你的回调或履行你的承诺。

以上都使用专用硬件而不是在CPU上执行指令来传输数据。因此

所以node.js中的并行性更多地与CPU支持多少PCIe通道有关,而不是它有多少CPU内核。

如果你愿意,可以异步执行javascript

和其他语言一样,现代javascript也支持多线程,在浏览器中以webworkers的形式存在,在node.js中以worker_threads的形式存在。但这是常规的多线程,就像任何其他语言一样,你故意启动另一个线程来异步执行你的代码。

最新更新