js 异步执行顺序

柔情痞子 提交于 2020-02-07 01:07:43
1.js的执行顺序,先同步后异步
2.异步中任务队列的执行顺序: 先微任务microtask队列,再宏任务macrotask队列
3.调用Promise 中的resolve,reject属于微任务队列,setTimeout属于宏任务队列
注意以上都是 队列,先进先出。
 
微任务包括 `process.nextTick` ,`promise` ,`MutationObserver`。
宏任务包括 `script` , `setTimeout` ,`setInterval` ,`setImmediate` ,`I/O` ,`UI rendering`。
在node环境下,process.nextTick的优先级高于Promise,也就是可以简单理解为:在宏任务结束后会先执行微任务队列中的nextTickQueue部分,然后才会执行微任务中的Promise部分。
 
javascript事件机制
 
题目1:
 
 
console.log('script start')  
async function async1() {
  await async2()
  console.log('async1 end') 
}
async function async2() {
  console.log('async2 end')
}
async1()

setTimeout(function() {
  console.log('setTimeout') 
}, 0)

new Promise(resolve => {
  console.log('Promise') 
  resolve()
})
.then(function() {
  console.log('promise1') 
})
.then(function() {
  console.log('promise2') 
})

console.log('script end') 

执行结果?

分析:

首先执行 同步代码:

1. 首先执行    console.log('script start')
2. 执行 async1() 的时候,马上执行了 async2函数:console.log('async2 end')
3. 顺序执行 new Promise()中的同步函数:console.log('Promise')
4. 最后执行  console.log('script end')。
上面是同步执行的代码,然后看剩下的异步执行的代码:
首先,setTimeout是 宏观任务,排除到最后,剩下微观任务:
async function async1() {
  await async2()
  console.log('async1 end') 
}
new Promise(resolve => {
  resolve()
})
.then(function() {
  console.log('promise1') 
})
.then(function() {
  console.log('promise2') 
})

5. 然后根据先入先出的对列方式,先执行  await async2() 后面阻碍的函数  console.log('async1 end') 

6. 执行promise的resolve函数

new Promise(resolve => {
  resolve()
})

也就是接下来的两个then: console.log('promise1') ----  console.log('promise2') ;

7. 最后执行的是 setTimeout函数  console.log('setTimeout') ;

综上所述,以上代码执行的顺序是:

1.script start 2.async2 end 3.Promise 4.script end 5.async1 end 6.promise1 7.promise2 8.setTimeout
 
题目2:
 
(function() {

    setTimeout(() => {
        console.log(0);
    });

    new Promise(resolve => {
        console.log(1);

        setTimeout(() => {
            resolve();
            Promise.resolve().then(() => console.log(2));
            console.log(3);
        });

        Promise.resolve().then(() => console.log(4));

    }).then(() => {
        console.log(5);
        Promise.resolve().then(() => console.log(8)); 
        setTimeout(() => console.log(6));
    });

    console.log(7);

})();

1. 同样先执行同步代码,且先把setTimeout去掉:

new Promise(resolve => {
      console.log(1);
      Promise.resolve().then(() => console.log(4)); //微观任务
  }).then(() => {                  //then函数是执行对应的 resolve 的时候才执行的
      console.log(5);
      Promise.resolve().then(() => console.log(8));//微观任务
 }); console.log(7);

可以看出先执行: console.log(1);console.log(7);

2. 执行微任务  Promise.resolve().then(() => console.log(4)); 

代码变成了:

(function() {
  setTimeout(() => {
      console.log(0);
  });
  new Promise(resolve => {
      setTimeout(() => {
          resolve();
          Promise.resolve().then(() => console.log(2));
          console.log(3);
      });
  }).then(() => {
      console.log(5);
      Promise.resolve().then(() => console.log(8)); //这句是多加的
      setTimeout(() => console.log(6));
  });
})();

只剩下宏观任务(微观任务在宏观任务里,也就是宏观任务外面不在有微观任务了)

3. 执行  console.log(0);

4.再执行 new Promise 中的  setTimeout,先执行里面的同步函数:console.log(3)

5. 再执行上面的 resolve,对应的是下面的then函数:

then(() => {
      console.log(5);
      Promise.resolve().then(() => console.log(8)); //这句是多加的
      setTimeout(() => console.log(6));
 }

所以先执行 console.log(5);

剩下的都是微观任务和宏观任务,先看微观任务:

 new Promise(resolve => {
      resolve();
      Promise.resolve().then(() => console.log(2));
  }).then(() => {
      Promise.resolve().then(() => console.log(8));
      setTimeout(() => console.log(6));
  });

所以根据队列中的微观任务顺序先执行:console.log(2),在执行then中的 console.log(8);

最后再执行 console.log(6)

综上所述,结果为 

1/7/4/0/3/5/2/8/6
 
题目3:
(function() {
    setTimeout(() => {
        console.log(0);
    });

    new Promise(resolve => {

        console.log(1);
        
        setTimeout(() => {
            resolve();
            Promise.resolve().then(() => {
                console.log(2);
                setTimeout(() => console.log(3));
                Promise.resolve().then(() => console.log(4));
            });
        });

        Promise.resolve().then(() => console.log(5));

    }).then(() => {

        console.log(6);
        Promise.resolve().then(() => console.log(7));
        setTimeout(() => console.log(8));

    });

    console.log(9);
})();
解释如下:【同步>异步;微任务>宏任务】
第一步:打印出1、9 ;如图
 
图a
由图a中的任务队列可知:
第二步: 执行微任务3,打印出 5
第三步:执行宏任务1,打印出 0
第四步:开始执行宏任务2;如图:
图b
第五步:由图b中的任务队列可知, 执行微任务4,打印出 6,如图:
图c
第六步:由图c中的任务队列可知, 执行微任务5,打印出2;如图 
图d
 

由图d的任务队列可知,
第七步:执行微任务6,打印出7
第八步:执行微任务9,打印出4
第九步:执行宏任务7,打印出8;
第十步:执行宏任务8,打印出3;

即答案是:

1-9-5-0-6-2-7-4-8-3

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!