码迷,mamicode.com
首页 > 其他好文 > 详细

事件循环的一些小啰嗦

时间:2021-03-16 14:03:37      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:div   类型   loop   queue   proc   同步   遇到   结束   settime   

首先,在说这个之前,我们先把event loop再复习一遍:

JS主线程不断的循环往复的从任务队列中读取任务,执行任务,其中运行机制称为事件循环(event loop).那么提到这里,在高层次上,JavaScript中有microtasks和macrotasks,它们是异步任务的一种类型.Microtasks的优先级要高于macrotasks,macrotasks用于处理I/O和计时器等事件.每次执行一个,microtask为async/await和Promise实现延迟执行,宁在每个task结束时执行.在每一个事件循环之前,microtask队列总是被执行完毕.

我们在看看经常见到的一些微任务与宏任务的区别:

1.微任务:process.nextTick,promise,MutationObserver

 2.宏任务:setTImeout,setTimeInterval,setImmediate,I/O,UI渲染

注意哈:每个event loop都会有一个microtask queue,也会有一个或多个macrotask queue,一次任务可以放入macrotask queue,也可以放入microtask queue中.每一次event loop,会首先执行microtask queue,执行完成后,会提取macotask queue的一个任务加入macrotask queue,接着执行microtask queue,依次执行下去直至所有任务执行结束.

 

我们再来看下异步执行机制吧.JS主线程拥有一个执行栈(同步任务)与一个任务队列,主线程回依次执行代码.当遇到同步任务时,会先将函数入栈,函数运行后再将该函数出栈;当遇到异步任务时,这些任务会返回一个值,让主线程不在此阻塞,使得主线程继续执行下去,而真正的任务交给了浏览器内核来执行,浏览器内核执行结束后,会将该任务事先定义好的回调函数加入相应的任务队列中.当JS主线程前空了执行栈后,会按先入先出的顺序读取microtasks queue的回调函数,并该函数入栈,继续运行执行栈,直到情况执行栈,再去读取任务队列.当微任务队列的任务执行完成后,会提取宏任务队列的一个任务加入微任务队列,接着继续执行微任务队列,依次执行下去直到所有任务全部执行结束.

接下来,我们来依次看看几个比较常用的异步:

1.setTimeout

console.log(‘start1‘);
setTimeout(function(){
console.log(‘macro‘);
},0)
console.log(‘22‘)
//输出顺序为:start1->22->macro

 

2.Promise

Promise本身是同步的立即执行函数,当在excutor中执行resolve或者reject的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会去调用resolve/reject中存放的方法执行

console.log(‘start‘)
let promise1=new Promise(function(resolve){
console.log(‘promise1‘)
resolve()
console.log(‘1end‘)
}).then(function(){
console.log(‘promise2‘)
})
setTimeout(function(){
console.log(‘setTimeout‘)
})
console.log(‘send‘)
//start->promise1->1end->send->promise2->setTimeout

当JS主线程执行到Promise对象时,promise1.then()的回调就是一个task,promise1是resolved或rejected,那这个task就会放入当前事件循环回合的microtask queue中.如果是pending,这个task就会放入事件循环的某个回合的microtask queue中,我们再来看些例子吧:

const p=Promise.resolve();//1.p的状态为resolve
(async ()=>{
await p;//2.返回,并将函数体后面的console放入下一个事件循环的microtask queue中
console.log(‘await end‘);//5.执行,打印
})();
p.then(()=>{
console.log(‘then 1‘);//3.p的状态变为resolve,会把p.then()放入当前事件循环的microtask queue中,因此打印then 1
}.then(()=>{
console.log("then 2");//4.打印then2
})
//输出:then 1->then 2->await end
console.log(‘start‘);
setTimeout(function(){
console.log(‘setTimeout‘)
},0)
Promise.resolve().then(
function(){
console.log(‘promise1‘)
}).then(function(){
console.log(‘promise2‘)
});
console.log(‘end‘);
//输出结果:start->end->promise1->promise2->setTimeout

3.async await

async function async1(){
console.log(‘async1 start‘);
await async2();
console.log(‘async2 end‘)
}
async function async2(){
console.log(‘async2‘)
}
console.log(‘script start‘)
async1();
console.log(‘script end‘)
//script start->async1 start->async2->scirpt end ->async2 end

 

async函数返回一个Promise对象,当函数执行的时候,一旦遇到await就会先返回,等到出发的异步操作完成,再执行函数体被那个后面的语句,可以理解为是让出了线程,跳出了async函数体.

事件循环的一些小啰嗦

标签:div   类型   loop   queue   proc   同步   遇到   结束   settime   

原文地址:https://www.cnblogs.com/ljylearnsmore/p/14537145.html

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