JS中的事件循环(EventLoop)和微任务与宏任务完全解析

互联架构唠唠嗑 2024-04-13 20:59:23
介绍首先,地球人都知道JS是单线程的,所以JS同时只能执行一个任务,也就是只有一个调用栈,先执行同步任务,再执行异步任务。虽然HTML5允许JS脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM。所以,这个新标准并没有改变JS单线程的本质。 什么是异步任务异步任务就是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。 什么是事件循环事件循环(Event Loop)是 JavaScript 引擎处理异步任务的机制。它用来管理所有的任务队列,包括宏任务和微任务队列。当 JavaScript 引擎遇到异步任务时,会将其放入相应的任务队列中,并继续执行同步代码,直到同步代码执行完毕或遇到下一个异步任务。当当前的宏任务执行完毕后,JavaScript 引擎会按照一定的规则从微任务队列中取出任务执行,直到微任务队列为空;然后再从宏任务队列中取出下一个宏任务执行。这个过程就是事件循环。 宏任务和微任务都有宏任务有事件的回调函数,新程序或子程序被直接执行\ 事件循环流程整体script作为第一个宏任务进入主线程,遇到console.log(Start),输出Start遇到setTimeout,其回调函数被分发到宏任务中遇到newPromise,new Promise构造函数执行,输出"这是Promise构造函数"遇到then被分发到微任务中遇到console.log("End"),输出End调用栈被清空以后 事件循环就会优先寻找微任务队列里面的任务我们发现了then在微任务里面,执行输出“这是Promise.then”第一轮事件循环结束,开始第二轮事件循环宏任务有setTimeout对应的回调函数,立即执行输出“这是定时器”输出结果Start这是Promise构造函数End这是Promise.Then这是定时器这次来个复杂的例子 宏任务嵌套微任务 微任务嵌套宏任务 这次把script这个大宏任务忽略 以同步任务角度开始看async function async1() {console.log("async1 start");await async2();console.log("async1 end");}async function async2() {console.log("async2");}console.log("script start"); setTimeout(function () {console.log("setTimeout1");});setTimeout(function () {console.log("setTimeout2");Promise.resolve().then(() => {console.log("then1");});Promise.resolve().then(() => {console.log("then2");});}); async1();new Promise((res) => {console.log("this is Promise");res();}).then(() => {console.log("then3");setTimeout(() => {console.log("then3 setTimeout3");});});console.log("script end"); 遇到函数async1 async2没有执行跳过遇到console.log('script start'),输出script start遇到setTimeout1其回调函数分发到宏任务中遇到setTimeout2其回调函数分发到宏任务中遇到async1()函数执行, 遇到console.log("async1 start"),输出async start在async1函数中遇到await async2() async2()优先级高于await运算符 async2()函数执行在async2函数中遇到console.log("async2")输出 async2回到async1函数中 ,由于async函数使用await后的语句会被放入一个回调函数中,所以await后续代码分发到微任务中遇到new Promise构造函数中 console.log("this is Promise"),直接执行 输出this is Promisethen方法被分发到微任务中遇到console.log("script end")同步任务执行完了 开始执行异步任务 根据eventloop先执行任务队列中的微任务任务队列先入先出 所以先输出'async1 end' 后输出 new Promise.then中的内容 then3,new Promise.then()中遇到setTimeout放到宏任务队列中,事件循环第一轮结束,开始第二轮宏任务队列setTimeout1拿出来输出事件循环第二轮结束,开始第三轮setTimeout2 执行 输出setTimeout1和setTimeout2setTimeout2中有两个.then方法分发到微任务 再执行输出 then1和then2事件循环第三轮结束,开始第四轮最后一个宏任务 输出 then3 setTimeout3所以代码输出结果script startasync1 startasync2this is Promisescript endasync1 endthen3setTimeout1setTimeout2then1then2then3 setTimeout3需要注意的是,微任务的执行顺序是按照它们被添加到微任务队列的顺序来执行的。即使某个微任务的产生时间晚于其他微任务,但如果它被添加到队列较早,那么它仍然会先于其他微任务执行。 文章到这里就结束了,希望对你有所帮助 作者:ZhaiMou链接:https://juejin.cn/post/7330300019022970915
0 阅读:2

互联架构唠唠嗑

简介:感谢大家的关注