前言
阅读本文前请先了解基本用法
Promise基本用法
宏任务与微任务
(大神的文章太多,这里就不展开讲了)
哪些API是微任务?
then、catch、finally
什么时候加入微任务队列?
当Promise转态为非pending时,api的回调加入微任务队列
new Promise((resolve,reject) => {
resolve()
}).then(() => {
console.log("then")
})
上述例子中,then的回调() => { console.log("then") }会被放到微任务中
实例分析
炼气
傻瓜例子
- point 宏任务与微任务执行先后
- 代码
Promise.resolve()
.then(() => {
console.log("then");
Promise.resolve().then(() => {
console.log("then-1");
});
})
console.log("out")
- 结果
out
then
then-1
- 分析
- 代码执行到
Promise.resolve().then - 前者Promise已经状态,所以then的回调放入微任务中
微任务队列压入代码:
() => {
console.log("then");
Promise.resolve().then(() => {
console.log("then-1");
});
}
3. 继续执行console.log("out"),输出out
4. 查看微任务,执行,输出then;继续执行到Promise.resolve().then
5. Promise已经状态,then的回调放入微任务中
微任务队列压入代码:
() => {
console.log("then-1");
}
6. 查看微任务,此时只有一个微任务,执行,输出then-1
笨蛋例子
- point
在then回调中执行
Promise.resolve(),相当于该then所返回的promise状态已经resolved - 代码
Promise.resolve()
.then(() => {
console.log("then1");
Promise.resolve().then(() => {
console.log("then1-1");
});
})
.then(() => {
console.log("then2");
});
console.log("out")
- 结果
out
then1
then1-1
then2
- 分析
- 执行到第一个
Promise.resolve().then,其回调压入微任务
微任务队列压入代码:
() => {
console.log("then1");
Promise.resolve().then(() => {
console.log("then1-1");
});
}
2. 继续看,第二个then由于上一个Promise状态还未定,所以其回调() => { console.log("then2");}
3. 执行console.log("out"),输出out
4. 执行微任务,输出then1;执行Promise.resolve().then,它的回调() => { console.log("then1-1"); }压入微任务中,此时第一个then的状态也变为了resolved,所以第二个then的回调也压入微任务中
微任务队列压入代码:
[
// 微任务1
() => {
console.log("then1-1");
},
// 微任务2
() => {
console.log("then2");
}
]
5. 执行微任务,输出then1-1,then2
筑基
开窍例子
- point 在then回调中,return一个非promise
- 代码
Promise.resolve()
.then(() => {
console.log(1);
Promise.resolve()
.then(() => {
console.log(2);
return 3;
})
.then((data) => {
console.log(data);
});
})
.then(() => {
console.log(4);
})
.then(() => {
console.log(5);
})
.then(() => {
console.log(6);
});
- 结果
1
2
4
3
5
6
- 分析
- 输出1,这时候内部的
Promise.resolve()改变了第一个then的状态,所以将下列代码压入了微服务
微任务队列压入代码:
[
() => {
console.log(2);
return 3;
},
() => {
console.log(4);
}
]
2. 执行微服务1,输出2,返回3,将后续的then回调压入微服务队列
微任务队列压入代码:
(data) => {
console.log(data);
}
3. 执行微服务2,输出4,将后续的then回调压入微服务队列
微任务队列压入代码:
[
(data) => {
console.log(data);
}
() => {
console.log(5);
}
]
4. 执行微任务1,入参为3,输出3;执行微服务2,输出5,将后续回调压入微任务,随后执行输出6
掉级例子
- point 在then回调中,return一个promise.resolve()
- 代码
Promise.resolve()
.then(() => {
console.log(1);
Promise.resolve()
.then(() => {
console.log(2);
return Promise.resolve(3);
})
.then((data) => {
console.log(data);
});
})
.then(() => {
console.log(4);
})
.then(() => {
console.log(5);
})
.then(() => {
console.log(6);
})
.then(() => {
console.log(7);
});
- 输出
1
2
4
5
6
3
7
- 分析
- 你品,你细品
- 简单来说,then里面返回了resolve的话,那接下来的then会落后两个微任务队列,即这里的
console.log(5);和console.log(6);,然后才压入微任务队列
复活例子
-
point 在then回调中,new Promise并resolve,return一个promise.resolve()
-
代码
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");
});
return new Promise((resolve, reject) => {
console.log("6");
resolve();
})
.then(() => {
console.log("7");
})
.then(() => {
console.log("8");
});
})
.then(() => {
console.log("9");
});
- 输出
1
2
3
6
4
7
5
8
9
- 分析
- 输出1,2
- 输出3后,第一个then回调里:内部第一个Promise状态变为resolved,注册
console.log("4")微任务;此时该宏任务未结束,继续执行到return,new了内部第二个Promise,执行同步代码console.log("6"),将该Promise状态改为resolved,将后续console.log("7")注册到微任务队列;注意,此时第一个then的状态未改变,所以不会注册第二个then回调console.log("9")到微任务队列里 - 执行微任务,输出4,7,(中间省略分析)5,8,这时第一个return返回的Promise状态变为resolved,注册第二个then回调
console.log("9")到微任务队列里,执行
金丹
等我追追星再补上,我怕是练不成金丹了....
升级例子
- point promise与async结合
- 代码
async function async () {
console.log('async start');
await new Promise(resolve => {
console.log('promise')
})
console.log('async success');
return 'async end'
}
async().then(res => console.log(res))
- 输出
async start
promise
- 分析
这里需要注意的是,由于await后面的promise状态并未改变,一直都是
pending,所以后续代码不会执行!只会等待!
泥淖风波例子
- 理解then中的return
- 代码
new Promise(resolve => {
resolve();
}).then(() => {
setTimeout(() => {
console.log(1);
Promise.resolve();
}, 4000)
}).then(() => {
setTimeout(() => {
console.log(2);
}, 1000)
})
- 输出
2
1
- 分析 看到没有,是2 1不是1 2!原因就在于第一个then中,虽然是延时4s才resolve,但是它没有return!!!在then中没有return或者return一个非promise,该then状态自动变为resolved!
爱谁谁
- 理解同级then
- 代码
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.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(data => console.log(data))
- 分析 then 方法接受的参数是函数,而如果传递的并非是一个函数,它实际上会将其解释为 then(null),这就会导致前一个 Promise 的结果会穿透下面
- 结果
1