执行栈 同步任务 异步任务 宏任务 微任务 总结(含面试讲解)

同步异步任务

JS中所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

同步任务指的是:
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

console.log 、方法调用就是同步任务

异步任务指的是:
不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。

宏微任务

异步任务又分为宏任务和微任务

1.宏任务

  • 定时器

  • 事件绑定

  • ajax

  • 回调函数

  • Node中fs可以进行异步的I/O操作

2.微任务

  • Promise(async/await) => Promise并不是完全的同步,在promise中是同步任务执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到微任务队列。当主栈完成后,才会再去调用resolve/reject方法执行

  • process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)

  • MutationObserver (创建并返回一个新的 MutationObserver 它会在指定的DOM发生变化时被调用。)

执行顺序优先级:SYNC => MICRO => MACRO

所有JS中的异步编程仅仅是根据某些机制来管控任务的执行顺序,不存在同时执行两个任务这一说法

微任务是可以嵌套的,里面可以在调各种任务

简单考察

看例子:
arcade复制代码setTimeout(()=>{
  console.log('setTimeout1')
},0)
let p = new Promise((resolve,reject)=>{
  console.log('Promise1')
  resolve()
})
p.then(()=>{
  console.log('Promise2')    
})

最后输出结果是Promise1,Promise2,setTimeout1
Promise参数中的Promise1是同步执行的
其次是因为Promise是微任务,会在同步任务执行完后会去清空microtasks queues,
最后清空完微任务再去宏任务队列取值。

面试常考题目做题方法

同步任务 => 异步任务( 微任务 => 宏任务 )
执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕

宏微任务里面也能嵌套宏微任务

下面是经典题目

setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)
//输出结果为 1、2、3、4

可以看出Promise比setTimeout()先执行。因为Promise定义之后便会立即执行,其后的**.then()是异步里面的微任务**,而setTimeout()是异步的宏任务。异步任务中先执行微任务后执行宏任务。

也就是说, promise 在实例化的过程中所执行的代码都是同步进行的,而 then 中注册的回调才是异步执行的。
在同步代码执行完成后才会去检查是否有异步任务,并执行对应的回调,而微任务又会在宏任务之前执行。

console.log("同步任务1");function workFun(mac) {
    console.log("同步任务2");
    if (mac) {
        console.log(mac);
    }
    return new Promise((resolve, reject) => {
        console.log("Promise中的同步任务");
        resolve("Promise中回调的异步微任务")
    })
}
setTimeout(() => {
    console.log("异步任务中的宏任务");
    setTimeout(() => {
        console.log("定时器中的定时器(宏任务)");}, 0)
    workFun("定时器传递任务").then(res => {
        console.log('定时器中的:', res);
    })
}, 0)
workFun().then(res => {
    console.log(res);
})
console.log("同步任务3")

/*
** 同步任务1 
同步任务2
Promise中的同步任务
同步任务3
Promise中回调的异步微任务

异步任务中的宏任务
同步任务2
定时器传递任务
Promise中的同步任务
定时器中的: Promise中回调的异步微任务
定时器中的定时器(宏任务)
*/

过一遍执行栈,先执行同步任务

console.log(“同步任务1”);

workFun()

console.log("同步任务2");
    if (mac) {
        console.log(mac);
    }
    return new Promise((resolve, reject) => {
        console.log("Promise中的同步任务");
        resolve("Promise中回调的异步微任务")
    })

console.log(“同步任务3”)

排好了不进入主线程的异步任务

宏任务:setTimeout, then(res => {    console.log(res); })

微任务:workFun()里嵌套微任务---- resolve("Promise中回调的异步微任务")

先执行所有同步任务,产生结果:

console.log(“Promise中的同步任务”)为什么会先执行,----这是promise的

而resolve(“Promise中回调的异步微任务”)没执行–还在执行同步函数,这是个异步

同步任务1 
(执行同步任务workFun函数)
同步任务2
Promise中的同步任务
同步任务3

执行完同步任务,开始异步任务,执行当前所有微任务,产生结果:

Promise中回调的异步微任务

执行排好队的宏任务,也就是

setTimeout

then(res => { console.log(res); })

执行先前排队的setTimeout,依次执行里面的同步任务

console.log("异步任务中的宏任务");
workFun("定时器传递任务")

又排了两个宏任务,

setTimeout(() => {        console.log("定时器中的定时器(宏任务)");     }, 

console.log("异步任务中的宏任务");

此时宏任务:

.then(res => { console.log(‘定时器中的:’, res); })

setTimeout(() => { console.log(“定时器中的定时器(宏任务)”); },

产生结果:

异步任务中的宏任务
同步任务2
定时器传递任务

执行workFun里的同步任务后,执行workFun里的微任务

产生结果:

Promise中的同步任务

继续执行宏任务:

 workFun("定时器传递任务").then(res => {        console.log('定时器中的:', res);    })
  1. setTimeout(() => {        console.log("定时器中的定时器(宏任务)");     }, 0)
    

产生结果:.then(res => { console.log(‘定时器中的:’, res); })

定时器中的: Promise中回调的异步微任务
定时器中的定时器(宏任务)

总结

先执行同步和立即执行任务,比如说console.log()、new Promise()
再依次执行微任务,比如说thenable函数和catchable函数
当微任务执行完成后开始执行宏任务,比如说定时器、事件回调等

最后给道es6的,答案留给大家解答讨论

async function method() {
  await method2();
  console.log(1)
}

function method2() {
  const promise = new Promise((resolve) => {setTimeout(() => resolve(), 0)});
  return promise;
}

function main() {
  method()
  console.log(2)
}

main()

参考:

https://blog.csdn.net/weixin_45272449/article/details/122815949
链接:https://juejin.cn/post/6844903638238756878

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值