Event Loop 探秘:微任务、宏任务与单线程世界的奥秘
2023-10-24 13:34:29
序言:揭开 JavaScript 单线程的神秘面纱
JavaScript 是当今世界最流行的编程语言之一,它被广泛应用于 Web 开发、移动开发、游戏开发等领域。JavaScript 的一大特色是单线程执行,这意味着它一次只能执行一个任务。
单线程执行模型虽然简单易懂,但却带来了一个问题:当 JavaScript 执行一个耗时较长的任务时,整个浏览器都会被阻塞,导致其他任务无法执行。为了解决这个问题,JavaScript 引入了微任务和宏任务的概念,从而实现异步编程。
微任务与宏任务:异步编程的基石
微任务
微任务是指在当前执行栈中执行的任务,也是 JavaScript 中优先级最高的任务。当 JavaScript 引擎执行完一个任务后,它会检查微任务队列,如果有微任务,则立即执行它们。微任务队列是一个先进先出的队列,这意味着最早加入的微任务将首先执行。
宏任务
宏任务是指在当前执行栈之外执行的任务,包括诸如 setTimeout、setInterval、I/O 操作等。宏任务队列也是一个先进先出的队列,但它与微任务队列不同,宏任务队列中的任务只有在微任务队列为空时才会执行。
Event Loop:协调微任务与宏任务的执行
Event Loop 是 JavaScript 中的一个核心概念,它负责协调微任务和宏任务的执行。Event Loop 会不断地从微任务队列和宏任务队列中取出任务并执行它们。如果微任务队列中有任务,则 Event Loop 会优先执行微任务。如果微任务队列为空,则 Event Loop 会执行宏任务队列中的任务。
微任务与宏任务的执行顺序
在 Event Loop 的协调下,微任务和宏任务的执行顺序遵循以下规则:
- 当 JavaScript 引擎执行一个任务时,它会将该任务的微任务添加到微任务队列中。
- 当 JavaScript 引擎执行完一个任务后,它会检查微任务队列,如果有微任务,则立即执行它们。
- 当微任务队列为空时,JavaScript 引擎会检查宏任务队列,如果有宏任务,则执行它们。
- Event Loop 会不断地重复上述步骤,直到所有任务都执行完成。
实例演示:揭秘 Event Loop 的运作过程
为了更好地理解 Event Loop 的运作过程,我们来看一个实例演示:
setTimeout(() => {
console.log('宏任务');
}, 0);
Promise.resolve().then(() => {
console.log('微任务');
});
console.log('同步任务');
当我们运行这段代码时,会看到以下输出:
同步任务
微任务
宏任务
这个实例演示了微任务和宏任务的执行顺序。首先,JavaScript 引擎执行同步任务,即 console.log('同步任务')
。然后,JavaScript 引擎将宏任务 setTimeout
添加到宏任务队列中,并将微任务 Promise.resolve().then()
添加到微任务队列中。
当 JavaScript 引擎执行完同步任务后,它会检查微任务队列,发现微任务队列中有任务,于是立即执行微任务 Promise.resolve().then()
。微任务执行完成后,JavaScript 引擎会检查宏任务队列,发现宏任务队列中有任务,于是执行宏任务 setTimeout
。
小试牛刀:一题检验你的理解
现在,我们来做一道题检验一下你的理解:
在一个 JavaScript 程序中,有以下代码:
setTimeout(() => {
console.log('宏任务 1');
}, 0);
Promise.resolve().then(() => {
console.log('微任务 1');
});
setTimeout(() => {
console.log('宏任务 2');
}, 0);
Promise.resolve().then(() => {
console.log('微任务 2');
});
console.log('同步任务');
请问,这段代码的输出是什么?
答案:
同步任务
微任务 1
微任务 2
宏任务 1
宏任务 2
结语
通过本文,你已经对 JavaScript 中的 Event Loop、微任务、宏任务有了深入的了解。掌握了这些知识,你将能够更好地理解 JavaScript 的异步编程机制,并编写出更加健壮、高效的 JavaScript 程序。