这是重读红宝书(JavaScript高级程序设计 第4版)的第6篇文章,本节我们来看看期约:Promise是什么、如何使用、实例方法、静态方法,以及如何结合 async、await
本节涉及源码见仓库github.com/adamswan/Re…
1、期约基础
是什么
Promise是 一个类,也是一个对象,用于解决回调地狱问题
三个状态
Promise对象有三个状态:pending、fulfilled、rejected,状态只能变化一次,且不会再次变化
使用
new Promise() 创建一个 Promise 对象
a、 必须向构造函数中传入一个执行器函数(executor),它是一个立即执行的同步任务
b、 在执行器中,我们一般放异步任务
c、 异步任务成功时,调用 resolve 函数,它干了两件事:
将 Promise 的状态从 pending 设置为 fulfilled,随后触发 .then() 的第一个回调;
接收成功的结果(value),传入 .then() 的第一个回调
d、 异步任务失败时,调用 reject 函数,,它干了两件事:
将 Promise 的状态从 pending 设置为 rejected,随后触发 .then() 的第二个回调 或者 .catch()的回调;
接收失败的原因(reason),传入 .then() 的第二个回调 或者 .catch()的回调
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("高圆圆");
}, 1000);
});
p1.then((value) => {
console.log(value);
});
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("刘亦菲");
}, 2000);
});
p2.catch((reason) => {
console.log(reason);
});
2、期约方法
实例方法:.then()、catch()、.finally()
静态方法:
Promise.all( [p1, p2, p3] )
.all() 用于同时发多个请求。接受一个Promise数组,返回值是一个大Promise
所有小p成功后,大Promise才成功,所有小p成功的结果形成一个数组;
如果有一个小p失败,大Promise立即失败
Promise.allSettled( [p1, p2, p3] )
.allSettled() 用于同时发多个请求。接受一个Promise数组,返回值是一个大Promise
大Promise会等所有小p的状态落定后(成功 / 失败),再成功掉,因为要接手所有小p成功、失败的结果,所以大Promise只能是成功的
所有小p成功、失败的结果会形成一个对象数组
Promise.any( [p1, p2, p3] )
.any能同时发多个请求,接受一个Promise数组,返回值是一个大Promise
它和 .all() 相反,只要有一个小p成功,返回的大Promise就立即成功;
直到所有小p失败,大Promise才失败,失败结果形成一个数组
Promise.race( [p1, p2, p3] )
能同时发多个请求,接受一个Promise数组,返回值是一个大Promise
赛跑机制,只关注状态率先变化的小p
如果最先变化的小p成功,则大Promise成功
如果最先变化的小p 失败,则大Promise失败
3、异步函数
异步函数,也称为“async/await”
async
1、async 关键字用于声明异步函数, 它可以让函数具有异步特征,但总体上其代码仍然是同步求值的,如果不和 await 配合使用,那么函数还是同步的
2、如果 async 函数有返回值,那么值会自动被Promise.resolve()包装成一个成功的 Promsie
await
1、 await 关键字可以暂停异步函数代码的执行,等待Promise成功。如果失败,await 下面的代码都不会执行,因为它们相当于 .then() 的第一个回调
2、await 会暂停执行异步函数后面的代码,让出 JavaScript 运行时的执行线程。这个行为与生成器函数中的 yield 关键字是一样的,await 关键字同样是尝试“解包”对象的值,然后将这个值传给表达式,再异步恢复异步函数的执行。
3、await 后如果不是一个 Promise ,会被自动包装成一个成功的 Promsie