返回

异步本质在 JavaScript:事件循环入微探究

前端

从一道题浅说 JavaScript 的事件循环

阮一峰老师在其推特上曾提出这样一道题:“在浏览器中,假如触发一个click事件,浏览器会经历哪些阶段?”这道题看似简单,但实际上,回答好这道题,必须对 JavaScript 的事件循环有清晰的理解。

1. 同步任务与异步任务

首先,我们需要明确JavaScript是单线程的,即它一次只能执行一个任务。任务可以分为同步任务和异步任务。同步任务会阻塞当前线程,而异步任务不会。当浏览器执行JavaScript代码时,它会创建一个执行栈(Execution Stack)和一个事件队列(Event Queue)。同步任务会添加到执行栈中,而异步任务会添加到事件队列中。

2. 事件循环的运作机制

事件循环是一个不断循环的过程,它从事件队列中获取任务并将其添加到执行栈中。当执行栈中的任务执行完毕后,它会被移出执行栈,事件循环会继续从事件队列中获取下一个任务并将其添加到执行栈中。

3. 宏任务与微任务

事件队列中的任务可以分为两种类型:宏任务和微任务。宏任务包括脚本、setTimeout、setInterval和I/O操作等,而微任务包括Promise和MutationObserver等。宏任务和微任务的区别在于,微任务会在当前宏任务执行完毕后立即执行,而宏任务则会等到所有微任务执行完毕后才执行。

4. 回答一道题

现在,我们可以回到阮一峰老师提出的问题:“在浏览器中,假如触发一个click事件,浏览器会经历哪些阶段?”

当用户点击一个按钮时,浏览器会触发一个click事件。这个click事件是一个事件,它会被添加到事件队列中。然后,事件循环会从事件队列中获取这个click事件并将其添加到执行栈中。

接下来,浏览器会执行click事件的处理函数。这个处理函数是一个宏任务,它会阻塞当前线程。因此,在这个处理函数执行期间,浏览器不会执行其他任务。

当click事件的处理函数执行完毕后,它会被移出执行栈。然后,事件循环会从事件队列中获取下一个任务并将其添加到执行栈中。

如果事件队列中还有其他宏任务,那么这些宏任务也会被添加到执行栈中并依次执行。

当执行栈中的所有宏任务执行完毕后,浏览器会检查是否有微任务。如果有微任务,那么这些微任务会立即执行。

当所有微任务执行完毕后,事件循环会继续从事件队列中获取下一个任务并将其添加到执行栈中。

这个过程会一直重复,直到事件队列中没有任何任务为止。

5. 总结

通过回答阮一峰老师提出的问题,我们对 JavaScript 的事件循环有了更深入的了解。理解事件循环的运作机制可以帮助我们更好地编写 JavaScript 代码,从而构建健壮、响应迅速的 web 应用。