沃梦达 / IT编程 / 前端开发 / 正文

详解JS浏览器事件循环机制

事件循环是指JavaScript在运行过程中对各种事件进行处理的一种机制。它主要用来处理异步任务,比如定时器、事件监听等,以及它们的回调函数。

详解JS浏览器事件循环机制

什么是事件循环机制

事件循环是指JavaScript在运行过程中对各种事件进行处理的一种机制。它主要用来处理异步任务,比如定时器、事件监听等,以及它们的回调函数。

事件循环的四个主要组成部分

事件循环机制主要由以下四个部分组成:

  1. 调用栈(call stack) - 用于存储当前正在执行的代码,遵循先进先出(FIFO)的原则。如果当前代码需要执行其他函数,那就将这个函数放到调用栈顶部,等待当前函数执行完毕后再执行新的函数。

  2. 任务队列(task queue) - 用于存储异步任务的回调函数。当异步任务完成时,它的回调函数会被添加到任务队列中等待执行。

  3. 事件循环线程(event loop thread) - 负责监听调用栈和任务队列中的任务执行情况,并且不断循环检查它们之间是否存在执行完毕的任务需要被执行。

  4. 微任务队列(microtask queue) - 在任务队列中,首先执行的是微任务队列中的任务,之后才会执行普通任务队列中的任务。

事件循环的执行过程

事件循环的执行过程可以大致分为以下几步:

  1. JavaScript代码运行时会把同步任务按照执行顺序添加到调用栈中执行。

  2. 如果当前代码是异步任务,如setTimeout() 或者 DOM事件监听器,它们的回调函数会被放到任务队列中等待执行。

  3. 等待调用栈中的同步任务全部执行完毕后,事件循环线程开始不断地在任务队列中查找待处理的任务。

  4. 如果任务队列中有待执行任务,事件循环线程会将队列中的下一个任务放入调用栈中执行。

  5. 如果任务队列中的任务是微任务,它会先执行微任务队列中的任务,之后再执行普通任务队列中的任务。

  6. 循环以上步骤,直到任务队列和微任务队列中的任务全部执行完毕。

示例一

console.log(1);
setTimeout(function() { console.log(2); }, 0);
console.log(3);

这段代码会先输出1,然后输出3,最后输出2。这是因为setTimeout() 是一个异步函数,它的回调函数会被放到任务队列中等待执行。在输出1和3之后,事件循环线程开始检查任务队列中的任务,发现有一个待处理的任务,就将其回调函数放到调用栈中执行,于是输出2。

示例二

setTimeout(function() { console.log(1); }, 0);
new Promise(function(resolve, reject) { console.log(2); resolve(); }).then(function() { console.log(3); });
console.log(4);

这段代码的输出顺序是 2 4 3 1,这是因为Promise的.then() 方法是微任务,其回调函数会被添加到微任务队列中等待执行。当调用Promise的resolve()方法时,Promise.then()的回调函数会立即被添加到微任务队列中,于是先输出2。接着输出4,因为它是同步代码。然后输出3,因为微任务队列中只有一个任务。最后输出1,因为setTimeout的回调函数是普通任务队列中的任务。由于它的延时时间为0,所以它的回调函数会在微任务队列中 WaitingTime 程序执行结束后立即执行。

结论

事件循环是JavaScript中非常重要的一个特性,关于它的运作机制和细节,需要开发者们熟练掌握。在具体应用场景中,我们需要灵活掌握事件循环的实现方式,避免出现一些无法预料的bug,保障代码的稳定性和可维护性。

本文标题为:详解JS浏览器事件循环机制