宏任务和微任务

本文详细解释了JavaScript中的宏任务与微任务的区别,包括它们如何在事件循环中执行,以及在setTimeout、Promise、Node.js中的应用。通过代码示例展示了宏任务和微任务的执行顺序和优先级。
摘要由CSDN通过智能技术生成

宏任务和微任务

  • 宏任务和微任务都是异步任务,都属于一个队列,主要区别于执行顺序
  1. js机制
    遇到宏任务,像执行宏任务,将宏任务放入事件队列中,然后执行微任务,将微任务方式事件队列中,这两个队列不是一个队列,先从微任务中拿回调函数,然后再宏任务中拿宏任务的回调函数。
  2. 再等待异步任务准备的时候,js引擎先去执行其他任务,等到异步任务准备好了,再去执行回调
  3. 宏任务队列和微任务队列
    1. 宏任务:script、setTimeout、setInterval、postMessage、MessageChannel、及Node.js 环境中的setImmediate.
    2. 微任务: Promise.then、Object.observe、MutationObserver、及Node.js 环境中的process.nextTick
    • 宏任务是由宿主环境发起的,比如浏览器,node

事件循环 eventloop

  • 浏览器的事件循环由一个宏任务队列和多个微任务队列组成
  1. 首先执行第一个宏任务,全局script脚本,产生的宏任务和微任务进入各自的队列,执行完script的代码之后,把当前的微任务队列清空,完成一个事件循环
  2. 接着在取出一个宏任务,同样把在此期间产生的回调入队,在把当前的微任务队列清空。
  3. 宏任务队列只有一个,每一个宏任务都有一个自己的微任务队列。每轮循环都是一个宏任务和多个微任务组成的

代码示例

```javascript
setTimeout(function () {
    console.log("setTimeout");
    new Promise(function (resolve) {
        resolve()
    }).then(function() {
        new Promise(function(resolve) {
            resolve()
        }).then(function() {
            console.log("then4");
        })
        console.log("then2");
    })
})
new Promise(function (resolve) {
    console.log("promise1");
    resolve()
}).then(function () {
    console.log("then1");
})
setTimeout(function() {
    console.log("setTimeout2");
})
console.log(2)
queueMicrotask(() => {
    console.log("queueMicrotask1");
})
new Promise(function (resolve) {
    resolve()
}).then(function () {
    console.log("then3");
})
// promise1
// 2
// then1
// queueMicrotask1
// then3
// setTimeout
// then2
// then4
// setTimeout2
```
  • 首先在执行代码的时候,script为一个宏任务,先将此任务执行,然后进行接下来的代码。遇到setTimeout将该定时器放入宏任务队列中。无论是不是零秒。在运行下面的代码。遇到new Promise将其中的console.log语句执行。将promise.then()放入微任务队列中。遇到了setTimeout将该settimeout放入到宏任务队列中。遇到了console.log(2)同步代码,直接输出。然后将queueMicrotask,这一创建微任务的函数放入微任务队列中,接下来执行new Promise, 将promise.then方法放入微任务队列中,这一轮输出了 promise1 和2。接下来清空微任务队列。微任务队列中,有promise.then()。所以将console.log("then1")进行输出,然后将queueMicrotask的函数进行输出,即输出为queueMicrotask1,接下来清空promise.then函数,将console.log("then3")进行输出。这一轮微任务输出了then1, queueMicrotask, then3然后执行宏任务队列中的内容,宏任务队列是一个队列,所以遵循先进先出的原则。宏任务队列中的内容有两个settimeout。将第一个settimeout先进性输出\将console.log("setTimeout")进行输出。然后在settimeout中创建了一个new promise ,将这个promise放入微任务队列中。然后输出同步代码console.log("then2"),这一轮循环结束将微任务进行清空。微任务中只有一个promise.then(),即将then4输出。然后将宏任务队列中的最后一个settimeout执行。即为输出’settimeout2’、
    console.log("script start");
    function requestData(url) {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("settimeout");
                resolve(url)
            }, 2000)
        })
    }
    function getData() {
        console.log("getData start")
        requestData("why").then(res => {
            console.log("then-res", res);
        })
        console.log("getData end")
    }
    getData()
    console.log("script start");
    // script start   
    // getData start  
    // getData end    
    // script start   
    // settimeout     
    // then-res why   
    
  • 首先代码执行,先输出script start,然后执行getData(), 在该函数的代码执行过程中,输出getData start,requestData().then是异步函数进入微任务队列。然后执行下一行代码,输出getData end,执行完毕这个函数,然后回到全局作用域中,将script start进行输出。requestData().then首先要将setTimeout执行完毕才能执行这个微任务,输出同步代码,settimeout,然后执行promise.then方法,输出then-res ,why
console.log("script start");
function requestData(url) {
    return new Promise((resolve) => {
    setTimeout(() => {
        console.log("settimeout");
        resolve(url)
    }, 2000)
})
}
async function getData() {
    console.log("getData start");
    const res = await requestData("helloworld")
    console.log("then-res1", res);
    console.log("getData end");
}
getData()
console.log("script END");
async function async1 () {
    console.log("1")
    await async2()
    console.log("2")
}
async function async2 () {
    console.log("3")
}

console.log("4")
setTimeout(function () {
    console.log("5")
}, 0)
async1()
new Promise(function (resolve) {
    console.log("6")
    resolve()
}).then(function () {
    console.log("7")
})
console.log("8")
// 4      
// 1      
// 3      
// 6      
// 8      
// 2      
// 7      
// 5      
  • 代码执行,将async1 和async2 函数提升,输出console.log(4),这一行同步代码,然后执行到async1这个作用域中,然后执行console.log("1")这个同步代码,遇到await async2() 进入async2()代码块中,然后输出3, 没有显示返回,会包装一个promise.resolve(undefined),所以进入微任务队列中,然后继续下面代码的解析,进入new promise代码块中,输出console.log(6),然后将promise.then放入微任务队列中,执行后面的同步函数console.log(8) ,执行完毕之后,然后执行微任务队列中的语句,将awiat async2执行,然后输出2, 然后执行微任务队列的promise.then,然后将7输出,将这个微任务队列清空之后,然后执行宏任务队列中,settimeout,输出5
  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值