假设我有一些带有大量同步处理的回调。在执行期间,事件循环不能自由轮询传入事件。那么这些事件会发生什么?他们在某个地方排队等待以后处理,还是只是丢失了?
感谢。
答案 0 :(得分:1)
将它们添加到队列中并稍后处理:
JavaScript运行时包含一个消息队列,它是要处理的消息列表。功能与每条消息相关联。当堆栈为空时,将从队列中取出一条消息并进行处理。处理包括调用相关函数(从而创建初始堆栈帧)。当堆栈再次变空时,消息处理结束。
答案 1 :(得分:1)
他们在从事件队列中被拉出后按顺序排队和处理。
您的JS代码无法阻止新事件进入队列。
答案 2 :(得分:1)
事件循环不会轮询。因此,无法处理事件循环不会影响传入事件。
大多数现代操作系统(或类似unix的古老操作系统)在操作系统级别而不是应用程序级别处理I / O. POSIX标准要求操作系统至少支持select()
系统调用。 select()
函数是阻塞函数,大多数程序用它来处理非阻塞I / O.这句话听起来很矛盾,但事实并非如此。
我将使用select()
作为示例,但不同的操作系统还有其他非阻塞API,如poll()
和epoll()
以及重叠IO(Windows)。各种javascript引擎通常使用类似libuv的库来自动处理在编译时使用的API。
非阻塞API通常提供一个函数,如select()
,可阻止和等待应用程序正在侦听的任何I / O上的事件。为什么阻止?因为这是程序使用0%CPU时间的唯一方法。否则,该过程将忙于轮询,这将是非常低效的。
旁注:阻塞是什么意思?阻塞基本上是告诉操作系统的任何功能:嘿,我等着这个"事情"所以你可以将我从CPU共享时间表中删除,并且只有在""到达?
非阻塞I / O和阻塞I / O之间的区别不在于您永远不会阻塞,非阻塞I / O块在多个I / O上等待,而阻塞I / O块在单个I / O上等待。如果您想了解更多谷歌select()
POSIX功能的文档。
无论如何,javascript使用非阻塞I / O,因此它不会阻止从I / O读取,而是阻塞select()
或类似功能。当解释器执行javascript代码时,显然它不会同时调用select()
函数。因此,当解释器忙时,操作系统会缓冲发往该程序的任何I / O.
没有。操作系统通常不会轮询(然后再次依赖于设备驱动程序,但通常不会)。 I / O活动由中断处理。即使对于非中断驱动的I / O(例如USB),通常处理I / O的芯片组在其缓冲区已满时也会产生中断,因此OS会将数据复制到RAM中的OS缓冲区。有时对于高速设备,它甚至不是执行复制的操作系统,而是DMA控制器,一旦数据被复制到RAM就会产生中断。
最后,像鼠标点击和按键操作的GUI活动也是中断驱动的(早期版本的基于DOS的GUI管理器,如Windows 1.0使用轮询驱动的鼠标驱动程序,然后微软看到了Mac OS和传说的演示了它Apple的一名工程师放弃了他们没有进行过调查,因为那时鼠标驱动程序通常会触发中断。)
一个小的例外是javascript中的线程。我认为是线程中的web worker和node.js中的磁盘I / O处理程序。例如,在node.js中,磁盘I / O驱动程序被实现为在各个线程中阻塞I / O.因此node.js负责在将数据传递回事件循环之前缓冲数据。同样,所有OS缓冲层仍然存在:复制数据(例如OS)可以在node.js线程调用下一个read()
之前缓冲已完成的磁盘读取命令。在任何情况下,线程仍然通过I / O通道(管道或套接字或unix域套接字)与事件循环进行通信,因此我上面概述的所有内容仍然成立:如果主js线程忙,则OS将简单地缓冲来自线程的数据(或者如果它被阻塞,那么线程将直接阻塞,直到事件循环处理它们的I / O)。