js事件循环机制(event loop)之宏任务/微任务

2021-08-01 14:56

阅读:932

标签:一段   有一个   task   循环   一个   tar   接下来   tin   代码   原文链接:https://blog.csdn.net/qq_33207292/article/details/102624553 1.关于js js是单线程的,即主线程就只有一个 2.js事件循环 除了广义的同步任务和异步任务,对任务更细致费划分: macro-task(宏任务):包括整体代码 script,setTimeout,setInterval等micro-task(微任务):Promise的then的回调函数,process.nextTick,async 函数await下面的代码;等js执行的时候: 第一步:js 解释器识别所有 js 代码,将同步的代码放到主线程执行;异步的代码放到Event Table(事件列表)执行。这也是第一次宏任务执行完毕! 第二步:接下来执行所有的微任务。 之后一直循环第一步,第二步,也就是常说的Event Loop(事件循环) 事件循环可以用下面这张流程图理解   为了理解来分析一段较复杂的代码: console.log(‘1‘);setTimeout(function() { console.log(‘2‘); process.nextTick(function() { console.log(‘3‘); }) new Promise(function(resolve) { console.log(‘4‘); resolve(); }).then(function() { console.log(‘5‘) })})process.nextTick(function() { console.log(‘6‘);})new Promise(function(resolve) { console.log(‘7‘); resolve();}).then(function() { console.log(‘8‘)})setTimeout(function() { console.log(‘9‘); process.nextTick(function() { console.log(‘10‘); }) new Promise(function(resolve) { console.log(‘11‘); resolve(); }).then(function() { console.log(‘12‘) })}) 第一轮事件循环流程分析如下: 整体script作为第一个宏任务进入主线程,遇到console.log,输出1。 遇到setTimeout,其回调函数被分发到宏任务队列中。我们暂且记为setTimeout1。 遇到process.nextTick(),其回调函数被分发到微任务队列中。我们记为process1。 遇到Promise,new Promise直接执行,输出7。then被分发到微任务队列中。我们记为then1。 又遇到了setTimeout,其回调函数被分发到宏任务队列中,我们记为setTimeout2。 下表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。   对照上述的事件循环流程图 宏任务结束之后我们接下来就开始去查看微任务中是否有任务 如果有就执行所有的微任务 这里有两个微任务process1和then1 执行process1,输出6。执行then1,输出8。好了,第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。那么第二轮事件循环从setTimeout1宏任务开始: 首先输出2。接下来遇到了process.nextTick(),同样将其分发到微任务队列中,记为process2。new Promise立即执行输出4,then也分发到微任务队列中,记为then2 第二轮事件循环宏任务执行结束,执行两个微任务process2和then2。 执行process2,输出3。执行then2,输出5。好了,第二轮事件循环正式结束,这二轮的结果是输出2,4,3,5。那么第三轮事件循环从setTimeout2宏任务开始: 首先输出9。接下来遇到了process.nextTick(),同样将其分发到微任务队列中,记为process3。new Promise立即执行输出11,then也分发到微任务队列中,记为then3 第三轮事件循环宏任务执行结束,执行两个微任务process3和then3。 执行process3,输出10。执行then3,输出12。第三轮事件循环结束,第三轮输出9,11,10,12。 整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。 总结:下一个宏任务执行前会去查看微任务队列中是否有任务 有就执行所有的微任务 微任务全部执行完 再去执行下一个宏任务 在看一个列子: setTimeout(() => { console.log(1)}, 1000);setTimeout(() => { console.log(2)}, 500);new Promise((resolve,reject)=>{ console.log(3) resolve()}).then(()=>{ console.log(4)})第一轮事件循环流程分析如下: 整体script作为第一个宏任务进入主线程, 遇到setTimeout,其回调函数在1000s后被分发到宏任务队列中。我们暂且记为setTimeout1。 遇到setTimeout,其回调函数在500s被分发到宏任务队列中。我们暂且记为setTimeout2。 new Promise立即执行输出3,then会立刻分发到微任务队列中,记为then 第一轮事件循环宏任务执行结束,有一个微任务then,执行得到结果4 第二轮事件循环从setTimeout2宏任务开始: 输出2,没有微任务 第三轮事件循环从setTimeout1宏任务开始: 输出1,也没有微任务 所以最后输出3,4,2,1 总结: 宏任务并不是立马放入宏任务队列的而是等到时间到了之后在放入 微任务会立马放入微任务队列中 下面出两个题供大家练习??~~~~~ async function async1() { console.log(‘async1 start===2‘) await async2() console.log(‘async1 end===6‘) }async function async2() { console.log(‘async2===3‘)}console.log(‘script start===1‘)setTimeout(function () { console.log(‘setTimeout==8‘)}, 0)async1();new Promise(function (resolve) { console.log(‘promise1===4‘) resolve();}).then(function () { console.log(‘promise2===7‘)})console.log(‘script end===5‘)  async function async1() { console.log(‘async1 start===2‘) await async2() console.log(‘async1 end===7‘)}async function async2() { console.log(‘async2===3‘) new Promise((resolve, reject) => { console.log(‘promise0===4‘) setTimeout(() => { console.log(‘async2 promise===10‘) }, 0) })}console.log(‘script start===1‘)setTimeout(function () { console.log(‘setTimeout=== 9‘)}, 0)async1();new Promise(function (resolve) { console.log(‘promise1====5‘) resolve();}).then(function () { console.log(‘promise2===8‘)})console.log(‘script end=====6‘) ————————————————版权声明:本文为CSDN博主「小腰精」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_33207292/article/details/102624553js事件循环机制(event loop)之宏任务/微任务标签:一段   有一个   task   循环   一个   tar   接下来   tin   代码   原文地址:https://www.cnblogs.com/yongwunaci/p/14805759.html


评论


亲,登录后才可以留言!