码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2021-06-23 16:38:08      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:一段   有一个   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/102624553

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

标签:一段   有一个   task   循环   一个   tar   接下来   tin   代码   

原文地址:https://www.cnblogs.com/yongwunaci/p/14805759.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!