事件循环和任务队列

如有错误欢迎指正,谢~

我们都知道js是单线程语言,也就是只有一个线程,常称为主线程,在该线程中包含任务队列和执行栈

任务队列:

一些异步操作会将相关回调添加到任务队列中,而且不同的异步操作添加到队列的时间也不一样。

eg:

①onclick 等异步是当事件触发立即会将回调放到任务队列中。

②settimeout 会等到延迟时间到了再把回调放到任务队列中。

③像网络请求ajax是等到请求完成的时候再把回调放到任务队列中去。

执行栈:

执行栈就相当于一个全局方法,主方法,里面有个同步任务和异步任务,主线程在执行碰到同步任务就执行,碰到异步任务就将其回调放到任务队列中,执行完同步任务之后,就开始执行任务队列了

具体怎么划分看下面:

macrotasks(就是我们平常说的任务队列)和microtasks的划分:

macrotasks包括:script (整体代码),setTimeout,setInterval,setImmediate,

microtasks包括:process.nextTick,Promises,Object.observe,MutationObserver

宏观任务和微观任务可以这么理解:

宏观任务1 队列          -------------------对应一个微观任务---------------   微观任务1队列

宏观任务2 队列         -------------------对应一个微观任务---------------    微观任务2队列

        ...                                                                                                            ...

宏观任务n 队列         -------------------对应一个微观任务---------------    微观任务n队列

执行全部宏观任务队列1之后再去取微观全部1任务执行,任何执行完 ,第二轮宏观任务2队列执行全部执行完毕执行全部微观任务2,然后第3轮。。。。。循环下去

那么我们来看一个例子:

eg1:

 1 setTimeout(function(){
 2     console.log(1)
 3 },0);
 4 new Promise(function(resolve){
 5     console.log(2)
 6     for( var i=100000 ; i>0 ; i-- ){
 7         i==1 && resolve()
 8     }
 9     console.log(3)
10 }).then(function(){
11     console.log(4)
12 });
13 console.log(5);

结果是

2,3,5,4,1

eg2:

 1 setTimeout(function(){
 2     console.log(1)
 3 },0);
 4 setTimeout(function(){
 5     console.log(6)
 6 },2000);
 7 new Promise(function(resolve){
 8     console.log(2)
 9     for( var i=100000 ; i>0 ; i-- ){
10         i==1 && resolve()
11     }
12     console.log(3)
13 }).then(function(){
14     console.log(4);
15     setTimeout(function(){
16         console.log(8)
17     },1000)
18 });
19 console.log(5);

这个执行结果是啥呢???想想

结果是:

2,3,5,4,1,8,6

 eg3:

setImmediate(function(){
  console.log(1);
},0);
setTimeout(function(){
  console.log(2);
},0);
new Promise(function(resolve){
  console.log(3);
  resolve();
  console.log(4);
}).then(function(){
  console.log(5);
});
console.log(6);
process.nextTick(function(){
  console.log(7);
});
console.log(8);

node 环境下:

3,4,6,8,5,1,2,7

浏览器环境下:

settimeout  优先级大于 setImmediate

nextTick 优先级 大于 promise

3,4,6,8,7,5,2,1

 eg4:

//加入两个nextTick的回调函数
process.nextTick(function () {
  console.log('nextTick延迟执行1');
});
process.nextTick(function () { 
  console.log('nextTick延迟执行2');
});
// 加入两个setImmediate()的回调函数
setImmediate(function () {
  console.log('setImmediate延迟执行1'); 
  // 进入下次循环 
  process.nextTick(function () {
    console.log('强势插入');
  });
});
setImmediate(function () {
  console.log('setImmediate延迟执行2'); 
});
 
console.log('正常执行');

浏览器环境下:正常执行,nextTick延迟执行1,nextTick延迟执行2,setImmediate延迟执行1,强势插入,setImmediate延迟执行2

 1 async function async1(){
 2     console.log("async1 start");
 3     await async2();
 4     console.log("async1 end");
 5 }
 6 async function async2(){
 7     console.log("async2");
 8 }
 9 console.log("script start");
10 setTimeout(function(){
11     console.log("settimeout");
12 },0);
13 async1();
14 new Promise(function(resolve){
15      console.log("promise1");
16      resolve()
17 }).then(function(){
18     console.log("promise2");
19 })
20 console.log("script end");

//结果

script start
async1 start
async2
promise1
script end
promise2
async1 end
settimeout

宏任务1队列:script start ,  async1 start , async2  ,promise1 , script end ----微任务队列1:promise2   (undefined) => { }(await Promise.resolve(undefined)的then(undefined){ (undefined) => { 这里才能拿到resolve的结果为undefined, 这是一个回调,异步操作,所以放到微任务中}})

宏任务2队列:settimeout     -----微任务队列2  空空如也

总结一下,便于自己学习,也分享大家一起学习。(#^.^#)

原文地址:https://www.cnblogs.com/zhanghaiyu-Jade/p/11123762.html