JS异步执行顺序

JS异步执行顺序

今天在重温promise的时候,突然发现了一个有趣的题目:

(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 5 0 6 2 7 4 8 3

简要讲述

首先我们知道JS分为了同步和异步,并且是顺序是先同步后异步,也就是同步代码执行完成后,哪怕异步代码到了它执行的时候,也会先让同步执行完。但是JS的执行顺序还可以分得更细,那就是异步的顺序。
我们知道很多异步任务,比如:

setTimeout, setInterval, setImmediate, Promises.then, Promise.catch

甚至还有nodejs中的process.nextTick等,就像我们知道process.nextTick比promise先执行一样。那么这些异步事件是谁先执行谁后执行呢。
这涉及到了事件循环(event loop)。事件循环也就是事件出入栈。
上面说了这么多异步任务,我们先把它们分为两类:
宏任务(macro-task):setTimeout, setInterval, setImmediate
微任务(micro-task):Promises.then, Promise.catch

然后我们再明白一个概念:先执行微任务,再执行宏任务。这种执行是,先执行清空微任务队列,再执行宏任务,当当前宏任务执行完后,微任务队列中又有微任务,再次将微任务队列执行完,再执行下一个宏任务。

在异步任务执行过程中遇到宏任务与微任务,将其依次放入当前事件循环队列中。

例题描述

首先执行主线程,也就是script(script是宏任务),因为此时没有微任务

然后遇到setTimeout(() => { console.log(0);}); 这是宏任务,将其放入宏任务队列中 记为 – 宏任务1

promise新建后会立即执行,输出1

然后将

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

继续放入宏任务队列中 记为 – 宏任务2

Promise.resolve().then(() => console.log(5));放入微任务队列中 记为 – 微任务1

继续往下走,输出9

此时当前宏任务执行完毕,开始执行微任务队列,目前微任务队列中只有微任务1,执行,输出5

微任务队列此时清空,然后执行宏任务1,输出0

微任务队列依然没有任务,继续执行宏任务2,遇见 resolve();,于是将

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

放入微任务队列中,记为 – 微任务2,再将

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

记为 – 微任务3

当前宏任务执行完毕,开始执行微任务,先执行微任务2,输出6;将Promise.resolve().then(() => console.log(7));记为 – 微任务4;setTimeout(() => console.log(8));记为 – 宏任务3

执行微任务3,输出2;将setTimeout(() => console.log(3));记为 – 宏任务4;将Promise.resolve().then(() => console.log(4));记为 – 微任务5;

此时队列中依然有微任务,执行微任务4,输出7;执行微任务5,输出4;微任务队列执行完毕

执行宏任务3,输出8;执行宏任务4,输出3;全部执行完毕

那么我们的结果为1 9 5 0 6 2 7 4 8 3

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值