JavaScript 是一种单线程的编程语言,这意味着在同一时间只能执行一个任务。为了有效地处理并发操作,JavaScript 引入了事件循环(Event Loop)机制,其中宏任务(Macro Task)和微任务(Micro Task)在其中扮演着关键角色。
1. 什么是宏任务和微任务?
-
宏任务(Macro Task) 是 JavaScript 中执行的大块任务或代码块,它包括了一些常见的操作,如:
setTimeout
setInterval
setImmediate
(仅在 Node.js 中)- I/O 操作
- UI 渲染
- 事件处理
-
微任务(Micro Task) 是一个需要在当前宏任务完成后、下一个宏任务开始前立即执行的小任务。常见的微任务有:
Promise.then
、Promise.catch
、Promise.finally
MutationObserver
process.nextTick
(仅在 Node.js 中)
2. 事件循环与任务队列
JavaScript 的事件循环决定了宏任务和微任务的执行顺序。事件循环的基本流程如下:
- 执行全局代码:当 JavaScript 代码第一次运行时,首先会执行同步代码,这些代码被当作一个宏任务。
- 检查微任务队列:一旦宏任务完成,事件循环会检查并执行微任务队列中的所有任务,直到队列为空。
- 执行下一个宏任务:如果微任务队列为空,事件循环会从宏任务队列中取出下一个任务并执行。
- 重复上述步骤:这个过程会不断循环,直到所有任务执行完毕。
3. 宏任务与微任务的执行顺序
了解宏任务与微任务的执行顺序对于掌握 JavaScript 异步操作非常重要。以下是一些关键点:
- 微任务总是在当前宏任务结束后立即执行,优先级高于下一个宏任务。
- 如果在微任务中再次添加微任务,这些新添加的微任务会在当前微任务队列完成后立即执行。
示例代码:
console.log('Start'); setTimeout(() => { console.log('setTimeout'); }, 0); Promise.resolve().then(() => { console.log('Promise 1'); }).then(() => { console.log('Promise 2'); }); console.log('End');
执行顺序解释:
- 'Start' 和 'End' 是同步代码,首先执行。
setTimeout
是一个宏任务,它会在宏任务队列中排队,等待当前宏任务完成后执行。Promise.then
是一个微任务,它会在当前宏任务(即同步代码执行完毕后)立即执行。- 因此,微任务 'Promise 1' 和 'Promise 2' 会先于
setTimeout
的回调执行。 - 最后,
setTimeout
的回调会被执行。
输出顺序:
Start End Promise 1 Promise 2 setTimeout
4. 宏任务与微任务的应用场景
理解宏任务和微任务的执行机制可以帮助我们在开发中更好地控制异步操作,避免意外的执行顺序。
场景一:控制异步代码的执行顺序
假设我们希望某些异步代码在其他异步代码之后执行,利用微任务的高优先级特性,可以确保其顺序执行。例如,我们可以使用 Promise.then
来控制执行顺序,而不是使用 setTimeout
。
场景二:优化性能
在高频率的用户交互或动画渲染场景中,我们可以利用微任务来进行一些轻量的操作,如 DOM 更新或状态检查,而将耗时较长的操作放在宏任务中处理。这可以减少 UI 的卡顿,提升用户体验。
场景三:避免深度嵌套的回调
在一些复杂的异步操作中,如果直接使用宏任务(如 setTimeout
),可能会导致嵌套层级过深,难以维护。利用 Promise
创建微任务可以使代码更简洁、可读性更好,同时也更易于调试。
标签:setTimeout,代码,JavaScript,任务,Promise,执行 From: https://www.cnblogs.com/zx618/p/18357231