JavaScript 的事件循环(event loop)是用于处理异步操作和事件的机制。它是 JavaScript 单线程(single-threaded)执行模型的基础,允许 JavaScript 在执行其他任务时处理异步操作和事件的回调函数。
事件循环的概念如下:
1.JavaScript 引擎执行同步任务:当 JavaScript 引擎开始执行代码时,它会按照顺序执行同步任务,即从上至下逐行执行代码。
2.异步任务进入任务队列:当 JavaScript 遇到异步任务时,如setTimeout、Promise、Ajax 请求等,它会将异步任务交给相应的 Web API 处理,并继续执行后续代码。
3.任务队列中的任务加入事件循环:一旦异步操作完成,相应的回调函数会被放入任务队列中。
4.事件循环将任务队列中的任务移入执行栈:当 JavaScript 引擎空闲时,它会从任务队列中取出一个任务,并放入执行栈中执行。
以上过程会不断重复,构成了 JavaScript 的事件循环机制。事件循环的主要内容如下:
1.执行栈(Call Stack):用于存储 JavaScript 中的函数调用和执行上下文。执行栈按照后进先出(LIFO)的顺序管理函数的执行。
2.任务队列(Task Queue):用于存储异步操作完成后的回调函数。任务队列可以分为宏任务(macro task)和微任务(micro task)两类。
(1)宏任务包括整体代码块(script),setTimeout,setInterval,I/O 操作等。
(2)微任务包括Promise,MutationObserver,process.nextTick 等。
3.微任务队列(Microtask Queue):存储微任务的队列。微任务会在当前宏任务执行完之后立即执行。
事件循环的过程如下:
1.首先,执行栈中的同步任务执行完毕。
2.检查微任务队列,如果有微任务,则依次执行所有微任务。
3.当微任务清空后,检查宏任务队列。
4.选择最先进入宏任务队列的任务,将其对应的回调函数放入执行栈中执行。
重复 2-4 步骤。
这样,JavaScript 的事件循环持续运行,使得 JavaScript 可以处理异步操作和事件回调,并保持单线程的特性。
值得注意的是,JavaScript 是一个单线程执行的语言,事件循环保证了异步操作和事件回调的执行顺序,但不会并行执行多个任务。因此,长时间的运行任务可能会阻塞事件循环,导致页面无响应或卡顿。为了避免这种情况,可以使用 Web Workers 进行多线程处理。