2026/3/7 0:45:14
网站建设
项目流程
北京seo网站结构优化,wordpress文章设置仅会员可见,网页版微信可以发朋友圈吗,用wordpress做视频Event Loop#xff08;事件循环#xff09;是 JavaScript 执行机制里的核心知识点。不管是前端面试还是日常开发#xff0c;只要涉及异步操作#xff0c;就绕不开它。
这篇文章不玩高深术语#xff0c;用一套真实示例#xff0c;带你搞懂#xff1a;
同步任务、宏任务、…Event Loop事件循环是 JavaScript 执行机制里的核心知识点。不管是前端面试还是日常开发只要涉及异步操作就绕不开它。这篇文章不玩高深术语用一套真实示例带你搞懂同步任务、宏任务、微任务到底是什么它们的执行顺序和优先级特别提醒Promise.resolve()和.then()到底哪个才是微任务 为什么需要 Event LoopJS 是单线程语言意味着同一时刻只能执行一件事。比如执行以下同步代码console.log(A);console.log(B);console.log(C);执行结果必然是ABC这就是同步任务的特点顺序执行只有前一个任务执行完毕才会执行下一个任务。但在实际开发中我们经常会遇到网络请求、定时器等耗时任务。如果这些任务都采用同步执行的方式页面会被卡住用户体验极差。为了解决这个问题浏览器和 Node.js 设计了“异步队列 Event Loop”的机制先把耗时的异步任务挂起等同步任务执行完毕、主线程空闲时再回头执行异步队列里的任务。️ 同步任务、宏任务、微任务怎么分三者分类对比表类型代表示例同步任务普通函数、console.log、直接调用的函数宏任务Macrotask整个script文件、setTimeout、setInterval、setImmediate、MessageChannel浏览器、I/ONode.js微任务MicrotaskPromise.then()、MutationObserver、queueMicrotask、process.nextTickNode.js 专属核心执行顺序口诀一个宏任务 → 执行同步任务 → 清空微任务队列 → 执行下一个宏任务 → 循环往复✅ 浏览器执行顺序经典示例来看一个典型的混合任务示例理解执行顺序console.log(代码开始);setTimeout((){console.log(这是 setTimeout 回调);},0);Promise.resolve().then((){console.log(这是 promise 的回调);});console.log(代码结束); 输出结果代码开始 代码结束 这是 promise 的回调 这是 setTimeout 回调执行过程拆解整个script文件作为第一个宏任务首先执行其中的同步代码先输出代码开始再输出代码结束setTimeout属于宏任务会被放入宏任务队列等待下一轮 Event Loop 执行Promise.then()属于微任务会被放入微任务队列在当前宏任务的同步代码执行完毕后立刻执行当前宏任务的同步代码执行完后清空微任务队列执行Promise.then()的回调输出这是 promise 的回调微任务队列清空后执行下一个宏任务即setTimeout的回调输出这是 setTimeout 回调。核心结论同步任务 → 微任务 → 下一个宏任务❗ 重点误区Promise.resolve()本身不是微任务很多人会误以为Promise.resolve()本身是微任务但实际并非如此真正的微任务是.then()中的回调函数。来看这个验证示例console.log(程序启动);constp1Promise.resolve(第一个 Promise);constp2Promise.resolve(第二个 Promise);constp3newPromise(resolve{console.log(执行 p3 构造函数);resolve(第三个 Promise);});p1.then(valueconsole.log(value));p2.then(valueconsole.log(value));p3.then(valueconsole.log(value));setTimeout((){console.log(第一波 setTimeout);constp4Promise.resolve(第四个 Promise);p4.then(valueconsole.log(value));},0);setTimeout((){console.log(第二波 setTimeout);},0);console.log(程序结束); 输出结果程序启动 执行 p3 构造函数 程序结束 第一个 Promise 第二个 Promise 第三个 Promise 第一波 setTimeout 第四个 Promise 第二波 setTimeout 原因解析Promise.resolve()的作用只是返回一个状态已确定的 Promise 实例这个过程本身不会产生微任务只有调用.then()方法时传入的回调函数才会被加入微任务队列执行流程拆解先执行所有同步任务程序启动→执行 p3 构造函数Promise 构造函数内的代码是同步执行的→程序结束当前宏任务的同步代码执行完后清空微任务队列依次执行 p1、p2、p3 的.then()回调输出对应的内容微任务队列清空后执行下一个宏任务第一个setTimeout输出第一波 setTimeout其中的p4.then()被加入微任务队列立刻执行并输出第四个 Promise最后执行第二个setTimeout宏任务输出第二波 setTimeout。 MutationObserver监听 DOM 改变的微任务在浏览器中MutationObserver也是微任务的一种它的作用是监听 DOM 元素的变化当 DOM 发生指定变化时回调函数会被加入微任务队列。示例代码consttargetdocument.createElement(div);document.body.appendChild(target);constobservernewMutationObserver((){console.log(微任务: MutationObserver 回调执行);});// 配置监听监听属性变化和子元素变化observer.observe(target,{attributes:true,childList:true});// 修改 DOM触发监听target.setAttribute(data-role,123);target.appendChild(document.createElement(span));执行结果微任务: MutationObserver 回调执行解析修改 DOM 的操作是同步任务执行完毕后MutationObserver的回调会被加入微任务队列在当前宏任务执行完后立刻执行。⚡ Node.js 专属process.nextTick优先级最高的微任务在 Node.js 环境中有一个专属的微任务process.nextTick它的优先级比普通微任务如Promise.then()更高——在当前宏任务的同步代码执行完后会先执行所有process.nextTick的回调再执行其他微任务。示例代码console.log(启动);process.nextTick((){console.log(执行 process.nextTick);});Promise.resolve().then((){console.log(执行 Promise.then);});setTimeout((){console.log(执行 setTimeout);Promise.resolve().then((){console.log(setTimeout 中的 Promise);});},0);console.log(收尾); 输出结果启动 收尾 执行 process.nextTick 执行 Promise.then 执行 setTimeout setTimeout 中的 Promise✏️ queueMicrotask手动添加微任务如果需要手动将一个任务加入微任务队列可以使用queueMicrotask方法它的效果和Promise.then()一致都会在当前宏任务执行完后立刻执行。示例代码console.log(准备执行);queueMicrotask((){console.log(这是 queueMicrotask 回调);});console.log(执行完同步任务);输出结果准备执行 执行完同步任务 这是 queueMicrotask 回调️ 最终总结执行优先级表格优先级队列内容 最高process.nextTickNode.js 专属 第二Promise.then()、MutationObserver浏览器、queueMicrotask 最后宏任务setTimeout、setInterval、I/ONode.js、MessageChannel浏览器等核心执行流程当前宏任务执行完毕 → 清空所有微任务按优先级执行→ 执行下一个宏任务 → 循环往复 最后的金句Promise.resolve()只是创建了一个已确定状态的 Promise 实例本身不是微任务只有调用.then()后传入的回调函数才会被排进微任务队列面试中的异步顺序题核心考点就在这里千万别搞混啦