# 前言
- JS 中用来存储待执行回调函数的队列包含
宏队列
和微队列
- 宏队列:用来保存待执行的宏任务(回调),比如:
定时器回调
、DOM事件回调
和Ajax回调
- 微队列:用来保存待执行的微任务(回调),比如:
Promise回调
和MutationObserve回调
- JS 执行时会区别这两个回调:
(a)Js引擎首先必须先执行所有的初始化同步任务代码
(b)每次准备取出第一个宏任务之前,都要将微任务逐个取出并执行
# demo
setTimeout(() => {
console.log(1)
}, 0);
Promise.resolve(2).then(
value => { console.log(value ) }
)
输出顺序为:2 1
原因:setTimeout 是宏任务,Promise 是微任务
微任务 执行先于 宏任务:每次准备取出第一个宏任务之前,都要将微任务逐个取出并执行
setTimeout(() => {
console.log(1)
}, 0);
setTimeout(() => {
console.log(2)
}, 0);
Promise.resolve(3).then(
value => { console.log(value ) }
)
Promise.resolve(4).then(
value => { console.log(value ) }
)
输出顺序为:3 4 2 1
原因:微任务 执行先于 宏任务,有多个同种任务时,按顺序依次执行
setTimeout(() => {
console.log(1)
Promise.resolve(2).then(
value => { console.log(value ) }
)
}, 0);
Promise.resolve(3).then(
value => { console.log(value ) }
)
console.log(4);
输出顺序为:4 3 1 2
原因:
Js引擎首先必须先执行所有的初始化同步任务代码,所以先输出 4
微任务 执行先于 宏任务,所以先输出 3
每次准备取出第一个宏任务之前,都要将微任务逐个取出并执行 所以输出 1 2
即执行顺序为:同步代码 =》微任务 =》 宏任务 =》宏任务 里的 微任务
# 小试牛刀
const first = () => (new Promise((resolve, reject)=>{
console.log(3);
let p = new Promise((resolve, reject)=>{
console.log(7);
setTimeout(() => {
console.log(5)
resolve(6)
}, 0);
resolve(1);
})
resolve(2);
p.then(value=>{
console.log(value)
})
}))
first().then(value=>{
console.log(value)
})
console.log(4);
输出结果为:3 7 4 1 2 5
注意:
Promise
的执行器
是 同步 执行的
陷阱:Promise
的 状态只能改变一次,即p
这个Promise
执行完resolve(1)
时,状态已经改变为resolved
,等到执行宏任务 setTimeout
里的resolve(6)
时,这时不起作用了,所以不会输出 6。
setTimeout(() => {
console.log(0)
}, 0);
new Promise((resolve, reject)=>{
console.log(1);
resolve()
}).then(()=>{
console.log(2)
new Promise((resolve, reject)=>{
console.log(3);
resolve();
}).then(()=>{
console.log(4);
}).then(()=>{
console.log(5);
});
}).then(()=>{
console.log(6)
});
new Promise((resolve, reject)=>{
console.log(7)
resolve()
}).then(()=>{
console.log(8)
});
输出顺序为:1 7 2 3 8 4 6 5 0
注意:
Promise
里的执行器
和.then()
都是 同步 执行的,但.then()
里的方法是 异步 的;
网友评论