都2023年了,还有人没搞懂微任务与宏任务吗?

大家都知道JavaScript是一门单线程执行的编程语言。代码执行顺序就是解析一行执行一行。小伙心里就在想那假如上一行执行非常久,那下一行该咋办? 那就等待呗!还能咋整...
for (var i = 0; i < 1000000000; i++) {
console.log("我没完,你就等着吧~")
}
console.log("我等上面的任务结束呀");
通过以上代码可以很明显的看到,如果循环没执行完。下面写的代码也不执行,就要等着它! 那如果我们来写一个定时器呢?它需要等吗?
setTimeout(()=>{
console.log("你可别等我,会疯掉的~")
},10000)
console.log("我不等你啦,我先执行了");
通过2个极其简单的小粒子,我们就知道了。setTimeout是一个异步呗!还有哪些API是异步这里就不做多余的赘述了。 兄弟们只要明白异步任务不会去阻塞同步代码的执行~
上面已经把异步的概念给引了出来,接下来咱就可以研究研究微任务与宏任务了, 首先微任务与宏任务都是异步任务 他们2个之间不存在谁等谁这种事情了!只存在谁先推到异步队列,谁先执行的现象~
我相信大家在网上或者博客上,都看过这种图。或者类似的这种图。对吧~ 但是看完还是一脸懵逼的,估计占了70%
那下面我就来说一下,我对这2个任务执行顺序的理解。 仅供参考:
首先根据公式:同步任务>微任务>宏任务 优秀级从左到右!
console.log('我是同步任务1')
setTimeout(()=>{
console.log("我是你们的洪流猛兽,宏任务~")
})
console.log('我是同步任务2')
Promise.resolve().then(res=>{ console.log("我是你们的危险份子,微任务~") })
通过这简单的代码,套用上面的公式,咱已经就有答案了。打印出来肯定是
- 我是同步任务1
- 我是同步任务2
- 我是你们的危险份子,微任务~
- 我是你们的洪流猛兽,宏任务~
浏览器效果如下:
加大难度,如果宏任务里面套一个微任务呢,再看一下执行顺序
console.log('我是同步任务1')
setTimeout(()=>{
console.log("我是你们的洪流猛兽,宏任务~")
Promise.resolve().then(res=>{ console.log("我要跟着洪流猛兽,同流合污,微任务~") })
})
console.log('我是同步任务2')
Promise.resolve().then(res=>{ console.log("我是你们的危险份子,微任务~") })
好像也能套上面的公式:同步任务->微任务->宏任务
首先2个同步任务先跑~
- 我是同步任务1
- 我是同步任务2
然后再看微任务,有一个“危险份子” 执行吧~
- 我是你们的危险份子,微任务~
然后再执行宏任务,此时注意:这个宏任务里面“洪流猛兽”是一个同步的,然后Promise是异步的 所以:
- 我是你们的洪流猛兽,宏任务~
- 我要跟着洪流猛兽,同流合污,微任务~
浏览器效果如下:
咱再继续加难度,此时又大有不同哦..
console.log('我是同步任务1')
setTimeout(()=>{
console.log("我是你们的洪流猛兽,宏任务~")
Promise.resolve().then(res=>{ console.log("我要跟着洪流猛兽,同流合污,微任务~") })
})
console.log('我是同步任务2')
Promise.resolve().then(res=>{
console.log("我是你们的危险份子,微任务~")
setTimeout(()=>{
console.log("我与危险份子相互拥抱,宏任务~")
})
})
此时套用上面的公式好像就有点牵强了,按照上面公式走的话:同步任务>微任务>宏任务,如下:
- 我是同步任务1
- 我是同步任务2
- 我是你们的危险份子,微任务~
- 我与危险份子相互拥抱,宏任务~
- 我是你们的洪流猛兽,宏任务~
- 我要跟着洪流猛兽,同流合污,微任务~
此时大家想一下,这个结果对吗? 看打印结果吧
此刻明显就有了出入,这里就要引出一个概念了。就是宏任务队列与微任务队列
JS在执行代码时,遇到异步任务都会往队列里面推。 想象一个场景公司食堂排队:食堂管理员看见财务负责人,CEO,项目经理,销售部员工1,程序员1,销售部员工2 ,程序员3,程序员2。
管理员为了拍马屁肯定是按照:CEO->财务负责人->项目经理 直接安排他们VIP包房服务来一套 此刻他们的角色在代码中就是同步任务,先执行!
此刻管理员又看到,销售部员工1,程序员1,销售部员工2 ,程序员3,程序员2。那么他又要纠正一下队列了。
首先销售部的进微任务队列:销售部员工1,销售部员工2 优先在宏任务之前
然后技术部的进宏任务队列:程序员1,程序员2,程序员3 在后
这里再次引出公式:同步任务->微任务->宏任务。但是如果:销售部员工1与程序员1,两人是好基友。结伴同行排队呢
console.log('CEO')
setTimeout(()=>{
console.log("程序员2")
})
console.log('财务负责人')
Promise.resolve().then(()=>{
console.log("销售部员工1")
setTimeout(()=>{
console.log("程序员1")
})
})
此时管理员看到这情况,一样会把它们区分开。你是哪个队的,就站哪个队。。 骨子里面定死的,不是你跟谁后面,就有饭吃。
CEO,财务负责人 同步的任务,走~ 进包厢服务~
然后销售部的进微任务队列:销售部员工1,但是你后面跟着:程序员1,他不是你们销售部的,没资格站这里。去宏任务队列排着
然后技术部的进宏任务队列:程序员2,程序员1
所以顺序就是:
- CEO
- 财务负责人
- 销售部员工1
- 程序员2
- 程序员1
刚才还有一种情况,如果是宏任务后面跟着微任务呢? 比如程序员2带着销售部员工2呢?
console.log('CEO')
setTimeout(()=>{
console.log("程序员2")
Promise.resolve().then(res=>{ console.log("销售部员工2") })
})
console.log('财务负责人')
Promise.resolve().then(()=>{
console.log("销售部员工1")
setTimeout(()=>{
console.log("程序员1")
})
})
此时管理员看到这情况,一样会把它们区分开。你是哪个队的,就站哪个队。。
CEO,财务负责人 同步的任务,走~ 进包厢服务~
然后销售部的进微任务队列:销售部员工1,但是你后面跟着:程序员1,他不是你们销售部的,没资格站这里。去宏任务队列排着
此刻程序员1因为是被微任务队列赶出来的,所以要进宏任务,此刻进宏任务一看,为什么前面有个销售部呀?此刻他就呼叫管理员,你不管管么?他不是宏任务这个队的。管理员说:他的身份本来是可以优先的,但是他愿意站你们那个队,就让他站着,你就默默站后面吧!
然后技术部的进宏任务队列:程序员2,销售部员工2,程序员1
所以顺序就是:
- CEO
- 财务负责人
- 销售部员工1
- 程序员2
- 销售部员工2
- 程序员1
上面的场景大家一定要花一点想象力理解一下。接下来就是终极面试题了
console.log('CEO');
setTimeout(function () {
console.log('程序员1');
Promise.resolve().then(res => { console.log('销售4') })
new Promise(function (resolve) {
console.log('程序员2');
resolve();
}).then(function () {
console.log('销售5')
})
})
Promise.resolve().then(res=>{ console.log('销售1') })
new Promise(function (resolve) {
console.log('财务主管');
resolve();
}).then(function () {
console.log('销售2')
})
setTimeout(function () {
console.log('程序员3');
Promise.resolve().then(res => { console.log('销售3') })
new Promise(function (resolve) {
console.log('程序员6'); resolve();
}).then(function () {
console.log('销售6')
})
})
答案依次打印如下:
- CEO
- 财务主管
- 销售1
- 销售2
- 程序员1
- 程序员2
- 销售4
- 销售5
- 程序员3
- 程序员6
- 销售3
- 销售6
转载自:https://juejin.cn/post/7233238727081852989