事件循环(Event Loop)是一种计算机程序或编程语言运行时环境用于处理和调度事件(事件驱动编程范式)的机制。它主要用于处理异步操作和事件处理,是许多编程语言和运行时环境的核心概念之一,包括JavaScript、Node.js、浏览器等。
单线程执行:
- JavaScript是单线程的语言,即在任何给定的时刻,它只能执行一个任务。这是因为JavaScript的设计初衷是用于处理浏览器中的用户交互,多线程可能导致复杂的同步问题。
- 但JavaScript的单线程并不意味着它不能同时处理多个任务,而是通过事件循环来实现异步操作。
执行栈和任务队列:
- 事件循环中有两个主要的组成部分:执行栈(Execution Stack)和任务队列(Task Queue)。
- 执行栈用于存储当前执行的代码,是一个类似于函数调用栈的数据结构。
- 任务队列用于存储待处理的异步任务和事件回调函数。
为什么会有event loop:
因为js
是单线程的,如果某段程序需要等待一会再执行,后面的程序都会被阻塞,这样也就带来了一些问题。为了解决这个问题,js
出现了同步和异步两种任务,两种任务的差异就在于执行的优先级不同。event loop
就是对任务的执行顺序做了详细的规范。
同步和异步任务:
- 异步任务:异步任务分为宏任务和微任务。
- 常见的微任务有:Promise.then(),.then中的逻辑是微任务;process.nextTick(node环境)。
- 常见的宏任务有:setTimeout、setInterval、setImmediate(node环境)、xhr(发送网络请求),callback。
- 同步任务:除了上面的这些情况,都属于同步任务。
微任务和宏任务:
- 任务队列中的任务可以分为微任务(Microtask)和宏任务(Macrotask)两类。
- 微任务优先级高于宏任务,当执行栈为空时,事件循环首先处理微任务队列中的任务,然后再处理宏任务队列中的任务。
- 常见的微任务包括Promise的回调函数和
process.nextTick
(Node.js中的微任务)。 - 常见的宏任务包括定时器回调、事件处理函数、IO操作等。
在实际场景下大概是这么一个顺序:
1.把同步任务相继加入同步任务队列。
2.把同步任务队列的任务相继加入主线程。
3.待主线程的任务相继执行完毕后,把主线程队列清空。
4.把微任务相继加入微任务队列。
5.把微任务队列的任务相继加入主线程。
6.待主线程的任务相继执行完毕后,把主线程队列清空。
7.把宏任务相继加入宏任务队列。无time的先加入,像网络请求。有time的后加入,像setTimeout(()=>{},time),在他们中time短的先加入。
8.把宏任务队列的任务相继加入主线程。
9.待主线程的任务相继执行完毕后,把主线程队列清空。