上篇讲异步的时候,提到了同步队列和异步队列的说法,其实只是一种形象的称呼,分别表明主线程中的任务和任务队列中的任务,那么此篇咱们就来详细探讨这二者。html
1、来张图感觉一下html5
若是看完以为一脸懵逼,请继续往下看。promise
2、解析异步
咱们仍是拿上篇的例子作解析oop
step1:f一、Promise对象实例化、f2被放入主线程的堆内存中;spa
step2:Promise对象实例化后的同步代码块被放入主线程的执行栈中执行,而且产生的异步任务被放入任务队列;线程
step3:f1被放入主线程的执行栈中执行(打印“我是F1”),for循环产生的1000个定时器(异步任务)放入任务队列;3d
step4:f2被放入主线程的执行栈中执行,连续5次;code
step5:至此,主线程的执行栈中已经没有任务了,因而事件循环(event loop)机制从任务队列中取出一个任务放入主线程的执行栈中执行;server
step6:等待主线程的执行栈中又没有任务了,事件循环机制再次去任务队列中取出任务;
step7:重复第6步。
3、任务队列
上面提到了任务队列,任务队列就是等候执行的一系列任务,就比如锅里的饭,你只有把碗里的饭吃完了,才能再次去锅里再盛一碗(不要杠!);
只有主线程的执行栈中没有了任务,事件循环机制才会去任务队列拿任务去执行。
由刚开始的图,你也看到了,任务队列是分不一样类别而且是有优先级的。
优先级的话,micro-task > macro-task;
对于micro-task:process.nextTick > Promise.then
对于macro-task:setTimeout > setImmediate
Promise.resolve().then(()=>{ console.log('Promise1') setTimeout(()=>{ console.log('setTimeout2') },0) }) setTimeout(()=>{ console.log('setTimeout1') Promise.resolve().then(()=>{ console.log('Promise2') }) },0)
step1:
分析:开始任务队列里有微任务promise1和宏任务timeout1,第一次事件循环一看有微任务,二话不说,直接拿promise1到主线程跑(实际上是跑完全部的微任务);promise1运行结果是,控制台打印promise1,并生成一个宏任务timeout2。
step2:
分析:由于此时任务队列里只有宏任务,因而,根据队列规则以及优先级(这里只有一种宏任务,因此没有涉及到优先级),事件循环拿timeout1去主线程跑;
timeout1运行结果,打印setTimeout1,并生成一个微任务promise2,至此第一次事件循环结束。
step3:
分析:任务队列里有微任务promise2和宏任务timeout2,事件循环一看有微任务,二话不说,直接拿promise2到主线程跑;
运行结果,控制台打印promise2,此时任务队列只剩下一个宏任务timeout2。
step4:
分析:此时任务队列只有一个宏任务timeout2,事件循环二话不说,由于没得挑了嘛,直接拿到主线程去跑,控制台打印timeout2,至此结束,也是第二次事件循环结束。
因此,一次事件循环是跑完全部微任务并推一个宏任务到主线程的过程。