动机
对于Javascript和node.js,我试图理解线程池和Web API之间的区别。
我目前了解的内容
- 线程池:多线程平台,其中每个线程执行它们自己的操作。
- Web API:浏览器内置的API。它是事件循环的一部分,与调用堆栈和回调队列沿着启用Javascript中的异步操作。
我困惑的是
似乎线程池和API都使Javascript能够处理异步行为。
当Javascript执行单线程调用堆栈之外的代码时,它是否被发送到Web API,后者 * 使用 * 线程池为每个异步操作创建一个线程?
如果没有,那么Web API和线程池如何协同工作以给予Javascript异步功能?
1条答案
按热度按时间c0vxltue1#
"先做几件事"
我们不太清楚"Web API"是什么意思,没有内置的nodejs,nodejs中有很多不同的库,每个库都有自己的API(定时器、网络、http请求、加密、磁盘I/O等)。
如果你指的是TCP网络或者http网络,那么我可以解释几件事。
首先,nodejs使用了一个名为libuv的跨平台库,它负责nodejs环境和对操作系统的本地代码调用之间的大部分接口,包括文件I/O、定时器、磁盘I/O、网络等。
驱动大部分nodejs的事件循环在libuv中。
其次,线程池是用于某些阻塞操作的本地线程池,nodejs希望能够向Javascript提供异步接口。如果接口直接从Javascript转到阻塞本地代码实现,则该操作将阻塞,并将阻塞事件循环。因此,要使接口异步,在线程池中运行的本机代码操作的示例有磁盘I/O和一些耗时的加密操作。
然后,通过使用非阻塞操作系统API来完成网络连接,因此不需要使用本机线程或线程池。
似乎线程池和WebAPI都使Javascript能够处理异步行为。
本机操作系统(如网络、文件I/O等)的接口设计与事件循环相结合,实现了异步行为。
当Javascript执行单线程调用堆栈之外的代码时,是否将其发送到Web API,后者使用线程池为每个异步操作创建一个线程?
同样,我们也不清楚术语"WebAPI"的含义,nodejs并没有为了异步执行而向其发送内容。
如果没有,那么Web API和线程池如何协同工作以提供Javascript异步功能?
将术语"WebAPI"转换为"nodejsAPI",让我们来看看这样一个操作是如何工作的。
让我们看一下
fs.open()
,一个打开文件的函数,当你调用fs.open()
时,它会进入nodejs内置的Javascript库,检查参数,如果参数错误,则处理任何即时错误,并最终调用绑定函数,该绑定函数将来自Javascript的参数打包成本机代码可以处理的内容,然后调用本机代码函数。这些参数包括对传入fs.open()
的回调的引用。这个原生代码函数将参数转换成C/C ++可以使用的形式,从线程池中获取一个线程,然后在该线程中运行一个OS调用来打开所需的文件。然后立即返回到
fs.open()
的Javascript部分,fs.open()
的Javascript部分然后返回到您的Javascript,并且您的Javascript继续运行任何连续的Javascript代码行,直到它最终将控制返回到事件循环。同时文件打开操作正在另一个操作系统线程中运行。当它完成时,它将事件插入相应的事件队列(事件循环的一部分),并将它正在使用的线程返回到线程池。插入到事件队列中的此事件包括对最初传递到
fs.open()
的回调函数的引用以及与fs.open()
的结果关联的任何数据(其中包括错误或文件句柄)。稍后,当控制返回到事件循环时,它将看到文件I/O的事件队列有一个挂起的事件,它将从事件队列中获取该事件,并调用与该事件关联的完成回调,将与该事件关联的数据传递给它。此时,您的Javascript回调将运行,您将在该回调中获得
fs.open()
调用的结果。这是nodejs中的异步操作。现在,请记住,不是每个异步操作都使用线程池。例如,计时器不使用线程。事实上,它们甚至不使用操作系统级计时器,因为事件循环有自己的计时器实现。网络也不使用线程池。