判断事件执行顺序--理解JavaScript事件循环机制

相信很多小伙伴看面试题的时候都看到过这种问js执行顺序的问题,这个问题也困扰了我一段时间,以下是我看完几篇大佬的文章后的理解,希望对大家有帮助。

首先,你要知道javascript是单线程语言,js任务需要排队顺序执行,如果一个任务耗时过长,后边一个任务也的等着,为了解决这种情况,将任务分为了同步任务和异步任务;而异步任务又可以分为微任务和宏任务。
宏任务包括有:script( 整体代码),setTimeout,setInterval 等
微任务包括有:Promise.then,process.nextTick 等

代码示例:

话不多说,直接上代码,你能正确判断出输出顺序吗!

console.log('script start');

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

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

解析:

  1. 整体 script 作为第一个宏任务进入主线程,遇到 console.log,输出 script start
  2. 遇到 setTimeout,其回调函数被分发到 宏任务 中
  3. 遇到 Promise,Promise里的代码立即执行,输出 promise1,将其 then函数分到到 微任务 中
  4. 遇到 console.log,输出 script end
  5. 主线程中任务执行完后,就要执行分发到微任务中代码(存在微任务的话,那么就执行所有的微任务),输出 promise2
  6. 微任务执行完后再看下一个宏任务 setTimeout ,输出 setTimeout

结合图片哈,更容易理解!在这里插入图片描述
so,你猜对了没,再看一个复杂点的例子哈;

console.log('1');

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

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

接着来解析

  1. 整体 script 作为第一个宏任务进入主线程,遇到 console.log,输出 1
  2. 遇到 setTimeout,其回调函数被分发到 宏任务 中,记住 setTimeout - 1
  3. 遇到 process.nextTick,其回调函数被分发到 微任务 中
  4. 遇到 Promise,Promise里的代码立即执行,输出 7,将其 then函数分到到 微任务 中
  5. 遇到 setTimeout ,其回调函数被分发到 宏任务 中,记住 setTimeout - 2
  6. 主线程中任务执行完后,就要执行分发到微任务中代码,此时微任务中有第 3 步的 process.nextTick 和第 4 步的 Promise.then 方法,按顺序执行输出 6,8
  7. 微任务执行完后再看下一个宏任务 setTimeout - 1 ,遇到 console.log,输出 2
  8. 遇到 setTimeout - 1 中的 process.nextTick ,其回调函数被分发到 微任务 中
  9. 遇到 setTimeout - 1 中 Promise,Promise里的代码立即执行,输出 4,将其 then函数分到到 微任务 中
  10. 执行完这些任务后,再来执行分发到微任务中代码,此时微任务中有第 8 步的 process.nextTick 和第 9 步的 Promise.then 方法,按顺序执行输出 3,5
  11. 微任务执行完后再看下一个宏任务 setTimeout - 2 ,遇到 console.log,输出 9
  12. 遇到 setTimeout - 2 中的 process.nextTick ,其回调函数被分发到 微任务 中
  13. 遇到 setTimeout - 2 中的 Promise,Promise里的代码立即执行,输出 11,将其 then函数分到到 微任务 中
  14. 执行完这些任务后,再来执行分发到微任务中代码,此时微任务中有第 12步的 process.nextTick 和第 13 步的 Promise.then 方法,按顺序执行输出 10,12

所以,输出顺序应该是 1,7,6,8,2,4,3,5,9,11,10,12

总结:

主线程中任务执行完后,就要执行分发到微任务中代码,存在微任务的话,那么就执行所有的微任务,当前所有的微任务执行完再进入新的宏任务中执行宏任务中的代码,如果有微任务就分配到微任务的队列中,当前宏任务中的代码执行完后,再接着执行所有的微任务,然后再进入下一个宏任务…以此类推下去!

以上就是我的理解,不对的地方还请指正!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

濮家大少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值