0. 前言
- 宏任务和微任务可能部分道友并不是那么理解
- 之前看到一个解释 ,觉得还是不错的,就记下来了,加上自己的理解写出来记录下,但是忘了原文出处,如有侵权,请告知
- 需要了解JS运行机制例如事件循序等知识 EventLoop
1. EventLoop
- js是单线程的,同一时间只能做一件事情
- 宏任务(macrotask)和微任务(microtask)的区分主要是为了解决 JavaScript 引擎中不同任务之间的执行优先级问题。
1.1 同步任务异步任务
- 为了防止某个
耗时任务
导致程序假死
的问题,js 把待执行的任务分为了 2 类:- 同步任务 synchronous
- 又叫做
非耗时任务
,指的是在主线程
上排队执行的那些任务- 只有前一个任务执行完毕,才能执行后一个任务
- 异步任务
- 又叫做
耗时任务
,异步任务由 JS 委托给宿主环
境进行执行- 当异步任务执行
完成
后,会通知
JS 主线程 执行异步任务的回调函数
2. 执行顺序
- 宏任务和微任务的执行顺序是
先宏后微
。先
执行同步
代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,- 当所有
同步
代码执行完毕
后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
3. 具体宏任务划分 (macro)task
- 宏任务有:
script
标签的加载和执行 (可以理解为外层同步代码);- setTimeout/setInterval
定时器
;- UI rendering/UI事件 --
DOM 事件
处理程序;- postMessage,MessageChannel5.
- setImmediate,
- I/O(Node.js)
- AJAX 请求的回调函数
- 对于宏任务,JavaScript 引擎会将其添加到任务队列(task queue)中,在
当前
任务执行完毕
后按顺序依次
执行
4. 具体微任务划分 Microtasks
- 微任务有:Promise.process.nextTick(Node.js);
Promise
的 then 方法和 catch 方法- async/await 中的 await 表达式
- Object.observe(已废弃;Proxy 对象替代);
- MutaionObserver
监听器
。
- 对于微任务,JavaScript 引擎也会将其添加到任务队列中,但是微任务的执行在
当前
宏任务执行结束
后立即
进行 - 也就是说微任务具有更高的执行优先级,可以优先于下一个宏任务执行
5. 技巧
- 通过区分宏任务和微任务,我们可以更好地控制任务的执行顺序,提高应用程序的性能和响应速度
- 在处理一些异步操作时,可以使用 Promise 来代替普通的回调函数,并通过 then 方法和 catch 方法来实现更灵活、更高效的任务处理方式。
- 同时,在编写代码时需要注意,尽量避免在宏任务中进行耗时操作,以免影响其他任务的执行。
6. 练习
- 测试下
setTimeout(() => { console.log("1"); }); new Promise((resolve)=>{ console.log("2"); resolve() }).then(()=>{ console.log("3"); }) console.log("4");
- 结果 2 4 3 1
- 分析
- 先执行所有的同步任务
创建
Promise和 输出 4 都是 同步任务 先执行,
所以 2 4
- 在执行微任务
then是微任务 3- 在执行下一个宏任务
定时器 1
- 2 4 3 1