事件处理程序如何在javascript内部执行?

时间:2019-01-01 21:41:18

标签: javascript asynchronous message-queue event-loop

我了解到javascript是单线程的,并且任何异步任务仅在当前堆栈为空之后才执行。 setTimeout承诺,仅在当前功能完成后才执行。

我想知道浏览器在执行某些事件时如何调用事件处理程序函数。

当我们说要注册一个事件时,该在哪里注册? (消息队列,作业队列)?它在哪里保存在内存中,浏览器如何知道某个事件已发生?

与操作系统相关的事件会调用吗?

我已经看过philip roberts video,并且了解了事件循环的功能。

我想了解javascript的内部原理。

2 个答案:

答案 0 :(得分:1)

  

当我们说要注册一个事件时,该在哪里注册?它在哪里保存在内存中?

处理程序功能安装在您正在侦听的资源上。对于DOM事件,它是浏览器用于显示文档的DOM对象,用于保证它是JS对象,对于计时器,则有一个内部计时器对象(与DOM有关,因为计时器是在HTML和每个窗口中定义的)。

  

(消息队列,作业队列)?

否,注册事件处理程序时,这些内容将保持空白。仅当事件实际发生时,需要运行的处理程序才会进入队列。

  

浏览器如何知道某个事件已发生?与操作系统有关的事件会调用吗?

是的,最终事件是来自操作系统的,无论是网络数据包到达,发生超时还是在浏览器窗口上单击。 (只有很少的事件是从浏览器内部触发的)。然后,浏览器会检查哪些资源受系统事件影响(例如,单击了哪个DOM元素),然后触发相应的事件,以便可以根据需要安排任何处理程序。

答案 1 :(得分:1)

浏览器主线程是一个事件循环。这是一个无限循环,可保持进程正常运行。它等待事件并对其进行处理。这里的事件表示几种事情,例如:

  • 用户已与UI组件进行了交互(单击按钮,将鼠标悬停在某物上等)
  • API请求已返回响应
  • 访问操作系统资源的请求已完成

例如,这是主事件循环的Firefox代码:

while (!mExiting)
    NS_ProcessNextEvent(thread);

假设我们有以下代码:

function jsFunction() {
    console.log("prints first");
    // execute remote API call
    axios.get("url").then(reponse => {
        console.log("success");
    }).catch(error => {
        console.log("error");
    });
    console.log("prints second");
}

我们称这个函数为

jsFunction();

那么,这里发生的是以下情况:

  • 您具有执行此功能的单线程控制功能,可打印“先打印”。
  • 然后您具有该外部API调用,因此浏览器会将其作为请求发送到操作系统的网络层以执行http请求,并注册我们提供的该回调函数,以便在响应来自网络时执行该回调函数层,而不是等待这种情况发生,而是继续执行。
  • 继续执行它会打印“第二张照片”。
  • 当响应来自网络层时,事件循环将执行您提供的回调函数。该响应是发送到上述事件循环的事件。它会执行适当的回调,并根据响应状态显示“成功”或“错误”。

有关一般如何在浏览器和浏览器引擎中实现事件循环的更多实际说明,请参见Reference