美文网首页
宏任务、微任务

宏任务、微任务

作者: 糖糖不加糖_ | 来源:发表于2023-02-19 11:04 被阅读0次

https://juejin.cn/post/6844903999506923528

浏览器中

宏任务和微任务是指异步后,如何将异步函数划分到哪个队列中执行。
正常方法执行,会先从上到下顺序执行方法,这些都属于同步的方法(不包含下面的宏任务和微任务方法的分类。)

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

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

console.log(2)
// 这里执行同步的任务为,空的setTimeout方法,之后异步函数塞到宏队列里
// 执行new Promise到then之前的所有方法,把then塞到微队列里
// 在执行console.log(2)

执行顺序: 同步 > 微任务 > 宏任务

每执行一个新的宏任务之前会先去执行微任务队列的信息,直至都清空后,才会执行下一个宏任务(一般应用在宏任务与微任务回调函数中互相又有相应调用的存在时发生)

宏任务分类

宏任务.png

微任务队列

微任务.png
Promise这一段是同步的任务,同理async与Promise相同也是同步任务。只有.then()、catch()、finally()、和await后面的调用才是微任务,(ps:await同行的调用属于同步调用范围,下面的一行才是then函数中的)

详尽举例说明

下面例子中定时器setTimeout的定时都是0,若不是0的话,多个宏任务之前的执行顺序就会有改变,当时间特别短,比如说10ms、20ms等,没办法确定谁先执行,谨记哦!!!

1、在主线程上添加宏任务与微任务

console.log('-------start--------');

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

new Promise((resolve, reject) => {
    console.log('resolve执行前')
    resolve()
    console.log('resolve执行后,reject执行前')
    reject();
    console.log('reject执行后')
}).then(()=>{
    console.log('Promise实例成功回调执行');
})

console.log('-------e')

从上到下,按步骤走,转换为各队列中执行的方法(队列:先进先出),不是宏任务和微任务的直接放在同步队列里,是宏任务的,把回调函数放到宏队列里,是微任务的,把回调函数放到微任务里

是宏任务的,把回调函数放到宏队列里,是微任务的,把回调函数放到微任务里

// 同步队列
tongbu = [
    console.log('-------start--------'),
    setTimeout,     // 空的,只是一个函数,它的回调函数被放置到了宏队列里,
    // 执行下面的Promise方法,因为当前这段为同步的,不是微任务,后面的then内容放到微队列里
    new Promise((resolve, reject) => {  
      // 内部也属于同步数据,从上到下执行(也可自行转换为同步队列)
        console.log('resolve执行前')
        resolve()
        console.log('resolve执行后,reject执行前')
        reject();
        console.log('reject执行后')
    }),
    console.log('-------e')
]
// 微队列
wei = [
    console.log('Promise实例成功回调执行')
]
// 宏队列
hong = [
    console.log('setTimeout')
]

先执行同步队列,再微队列,最后在执行宏队列,所以得到的结果是

-------start--------
resolve执行前
resolve执行后,reject执行前
reject执行后
-------e
Promise实例成功回调执行
setTimeout

在微任务中创建微任务

后续空的方法就不写了,直接写需要执行的方法

setTimeout(_ => console.log(4))
new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
  Promise.resolve().then(_ => {
    console.log('before timeout')
  }).then(_ => {
    Promise.resolve().then(_ => {
      console.log('also before timeout')
    })
  })
})
console.log(2)

第一步转换,转换为以下的队列

tongbu = [
    resolve => {    // promise
        resolve()
        console.log(1)
    },
    console.log(2)
]
wei = [
    _ => {
        console.log(3)
        Promise.resolve().then(_ => {
          console.log('before timeout')
        }).then(_ => {
          Promise.resolve().then(_ => {
            console.log('also before timeout')
          })
        })
      }
]

hong = [
    _ => console.log(4)
]

在同步队列中获取到结果:1,2
微队列中继续进行转换,由上面已经转换的微队列里进行转换,现在就是转换成同步的执行队列了

// 由上述微队列转换为当前执行的同步队列
tongbu = [
    console.log(3),
]
wei = [
   _ => {
          console.log('before timeout')
        }).then(_ => {
          Promise.resolve().then(_ => {
            console.log('also before timeout')
          })
       }
]

得出同步队列的结果:3
微队列还需要继续转化

// 由上述微队列转换为当前执行的同步队列
tongbu = [
    console.log('before timeout')
]
wei = [
        _ => {
            console.log('also before timeout')
       }
]

最后得到的结果:

1
2
3
before timeout
also before timeout
4
async、await使用例子
setTimeout(_ => console.log(1))

async function async1() {
    console.log('async1 start')
    await async2();
    console.log('async1 end')
}
async function async2() {
    console.log('async2 -1')
    await aa();
    console.log('async2 -2')
    await bb();
}
async function aa () {
    console.log('aa 1')
}
async function bb () {
    console.log('bb1')
}
console.log('async1执行前')
async1();
console.log(6)

转化为以下

tongbu = [
    console.log('async1执行前'),
    () => {
        console.log('async1 start'),
        () => {
            await aa();
            console.log('async2')
            await bb();
        }
    },
    console.log(6)
]
wei = [
    console.log('async1 end')
]
hong = [
    _ => console.log(1)
]

首先能拿到一部分的同步结果,

举一个,两个微任务中创建微任务的详细例子
setTimeout(_ => console.log(1))
new Promise(resolve => {
  resolve()
  console.log('Promise 1')
}).then(_ => {
  console.log('Promise 1 then')
  Promise.resolve().then(_ => {
    console.log('Promise 2 then')
  }).then(_ => {
    Promise.resolve().then(_ => {
        console.log('Promise 3 then')
    })
  })
})
async function async1() {
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}
async function async2() {
    console.log('async2')
}
async1();
console.log(6)

// async1执行前  async1 start  async2 -1  aa 1  6  async2 -2  bb1  async1 end 1

宏任务里创建微任务

setTimeout(() => 微任务方法),ps:函数里返回微任务方法
setTimeout(() => new Promise(resolve => {
  console.log('setTimeout1 start')
  resolve();
  console.log(4)
}).then(_ => {
  console.log(5)
}))
setTimeout(() => new Promise(resolve => {
  console.log('setTimeout2 start')
  resolve();
  console.log(24)
}).then(_ => {
  console.log(25)
}))
new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)

// 结果值:1  2  3  setTimeout1 start   4   5   setTimeout2 start   24  25

当多个宏任务时,会先将每个宏任务中的数值都处理完后,才会去做下一个宏任务处理,不管里面是普通的同步任务还是微任务,都要完全处理完一个宏任务,才能处理下一个

setTimeout(微任务方法)

这个时候,相当于setTimeout没有相应的宏任务回调方法!!!! 因为在setTimeout(() => 操作)中,后面的操作才属于宏任务方法,前面的方法属于普通方法,如果前面是微任务方法,那就按微任务方法执行,若前面是同步方法,那就按同步方法逻辑执行

setTimeout(new Promise(resolve => {
  console.log('setTimeout1 start')
  resolve();
  console.log(4)
}).then(_ => {
  console.log(5)
}))
setTimeout(new Promise(resolve => {
  console.log('setTimeout2 start')
  resolve();
  console.log(24)
}).then(_ => {
  console.log(25)
}))
new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)

// 结果值:setTimeout1 start   4  setTimeout2 start  24   1   2   5  25  3

因为setTimeout中方法不是()=> 操作信息,这样的返回值,并且内部的方法是微任务方法,所以此时,setTimeout中的方法按照本身方法类型处理,现在他是promise微任务,自上而下顺序里,优先推入微任务队列里,一共有3个微任务,微任务.then之前是同步的,所以直接同步处理,得到上面结果

微任务中添加宏任务

setTimeout(_ => console.log(4))
new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
  Promise.resolve().then(_ => {
    console.log('before timeout')
  }).then(_ => {
    setTimeout(() => {
      console.log('微任务中的宏任务1')
    })
  })
})
new Promise(resolve => {
  resolve()
  console.log(21)
}).then(_ => {
  console.log(23)
  Promise.resolve().then(_ => {
    console.log('before timeout2')
  }).then(_ => {
    setTimeout(() => {
      console.log('微任务中的宏任务2')
    })
  })
})
console.log(2)

// 结果值:
// 1  21  2  3  23  before timeout  before timeout2  4  微任务中的宏任务1  微任务中的宏任务2

按顺序推入微任务队列和宏任务队列中,在前面的会优先处理,因为微任务中的宏任务是后被推入进队列中的,那么就后处理

node中

宏任务处理不是等前一个宏任务处理完才执行,microtask 会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行 microtask 队列的任务

setTimeout(()=>{
    console.log('timer1')
    Promise.resolve().then(function() {
        console.log('promise1')
    })
}, 0)
setTimeout(()=>{
    console.log('timer2')
    Promise.resolve().then(function() {
        console.log('promise2')
    })
}, 0)
// 结果为: timer1=>timer2=>promise1=>promise2

相关文章

  • 宏任务、微任务

  • 宏任务 微任务

    宏任务 1.事件绑定 2.定时器 3.ajax/跨域中的异步(http请求异步) 微任务 1.Promise不是n...

  • 宏任务&微任务

    宏任务 我们可以将每次执行栈执行的代码当做是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行) ...

  • 宏任务、微任务

    https://juejin.cn/post/6844903999506923528[https://juejin...

  • 微任务 宏任务

    微任务Microtask/Task 一次执行一个,一个执行完后检测当前(此次事件循环中)宏任务执行完,在下一个宏任...

  • 宏任务 微任务

    https://blog.csdn.net/zxc024000/article/details/76760966?...

  • 微任务宏任务

    宏任务:整段script代码(可以理解为外层的同步代码),settimeout,setInterval,ajax请...

  • 微任务和宏任务@小四@王云飞

    微任务和宏任务 微任务 和 宏任务 表示异步任务的两种分类。 微任务(microtask)和宏任务(macrota...

  • 2018-08-15 微任务 宏任务 MicroTask Mac

    微任务和宏任务 微任务(Microtask)宏任务(Microtask)process.nextTickPromi...

  • 宏任务和微任务

    [js 宏任务和微任务] .宏任务(macrotask )和微任务(microtask ) macrotask 和...

网友评论

      本文标题:宏任务、微任务

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