美文网首页
宏任务((macro)task)和微任务(microtask)

宏任务((macro)task)和微任务(microtask)

作者: _花 | 来源:发表于2021-04-10 22:11 被阅读0次
    • 宏任务

    (macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。
    JS分为同步任务和异步任务,同步任务都在主线程上执行,形成一个执行栈

    • 微任务

    microtask,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。
    在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

    运行机制

    在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

    • 执行一个宏任务(栈中没有就从事件队列中获取)
    • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
    • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
    • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
    • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
      自我理解如下:
    • 执行调用栈中的全局Script同步代码,这些同步代码有一些是同步语句,有一些是异步语句(比如setTimeout等);
    • 全局Script代码执行完毕后,调用栈Stack会清空;
    • 执行微队列microtask queue中所有任务,执行微任务A的过程中若又遇到微任务B,那么先按顺序执行同步事件,再执行微任务B中的异步事件,最后执行微任务A的异步事件
    • 执行宏队列macrotask queue中的任务
    宏任务包含:
    script(整体代码)
    setTimeout
    setInterval
    I/O
    UI交互事件
    postMessage
    MessageChannel
    setImmediate(Node.js 环境)
    
    微任务包含:
    Promise.then
    Object.observe
    MutaionObserver
    process.nextTick(Node.js 环境)
    

    举例

     let  foo = () => {
            console.log(111)
    
            setTimeout(()=>{
                console.log(333)
    
                new Promise((resolve1, reject1) =>{
                     
                    new Promise((resolve2,reject2) => {
                        console.log(444)
                        resolve2();
                    }).then(()=>{
                        console.log(666)
                    })
                  console.log(555)
                   resolve1(777);
                }).then(resolve => console.log(resolve))
                }, 0)
    
            new Promise((resolve, reject) =>
                resolve(222)
            ).then(resolve => console.log(resolve))
        }
    foo();
    
    

    ES6和ES7的不同写法

    //ES7里
    async function async1() {
      await async2()
      console.log('async1 end')
    }
    async function async2() {
      console.log('async2 end')
    }
    async1()
    
    //ES6里
    new Promise((resolve, reject) => {
      // console.log('async2 end')
      async2() 
      ...
    }).then(() => {
     // 执行async1()函数await之后的语句
      console.log('async1 end')
    })
    
    new Promise((resolve, reject) => {
       setTimeout(() => resolve(new Promise(res => res(333))), 2000)
    }).then(res => {
        console.log(res)
        return 222
    }).then().then(res => {
        console.log(res);
        return new Promise(res => {
            setTimeout(() => { res(666) }, 1000)
        }).then(res => {
            console.log(res);
            return 999
        })
    }).then(res => {
        console.log(res);
    })
    //结果
    333
    222
    666
    999
    

    如果在promise里面再写一个promsie的话,由于里面的promise的then要比外面的promise的then先执行,也就是说它的nextTick更先注册,如下代码

    new Promise((resolve, reject) => {
       setTimeout(() => resolve(new Promise(res => res(111))), 2000)
    }).then(res => {
        console.log(res);
        new Promise((resolve,reject) => {
             resolve( 222)
        }).then(res => {
            console.log(res);
        })
    return 333
    }).then(res => {
        console.log(res);
    })
    

    代码若更换成如下,在内嵌的promise里加上setTimeout,输出结果就会改变

    new Promise((resolve, reject) => {
       setTimeout(() => resolve(new Promise(res => res(111))), 2000)
    }).then(res => {
        console.log(res);
        new Promise(res => {
            setTimeout(() => { res(333) }, 1000)
        }).then(res => {
            console.log(res);
        })
    return 222
    }).then(res => {
        console.log(res);
    })
    

    相关文章

      网友评论

          本文标题:宏任务((macro)task)和微任务(microtask)

          本文链接:https://www.haomeiwen.com/subject/drhvkltx.html