Promise,翻译为承诺,是异步变成的一种解决方案,比传统的回调函数更加合理和更加强大
以往:
doSomething((result)=>{
doSomethingElse(result,(newResult)=>{
doThirdThing(NewReslt,(finalResult)=>{
console.log("得到最终结果:" + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
通过Promise
改写
doSomething().then((result)=>{
return doSomethingElse(result)
})
.then((newReslut)=>{
return doThirdThing(newResult)
})
.then((finalResult)=>{
console.log("得到最终结果:" + finalResult)
})
.catch(failureCallback)
感受到promise
解决异步操作的优点:
- 链式操作减低了编码难度
- 代码可读性明显增强
状态
promise
对象仅有三种状态
-
pending
(进行中) -
fulfilled
(已成功) -
rejected
(已失败)
特点
- 对象的状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态
- 一旦状态改变(从
pending
变为fulfilled
和从pending
变为rejected
),就不会再变,任何时候都可以得到这个结果
用法
all()
Promise.all()
方法用于将多个Promise
实例,包装成一个新的Promise
实例
const p = Promise.all([p1,p2,p3])
接受一个数组作为参数,数组成员都应为Promise
实例
实例p
的状态由p1,p2,p3
决定,分为两种
- 只有
p1,p2,p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1,p2,p3
的返回值组成一个数组,传给p
的回调函数 - 只有
p1,p2,p3
当中有一个被rejected
,p
的状态就会变成rejected
,此时一个被rejected
的实例的返回值,会传给p
的回调函数
注意,如果作为参数的Promise
实例,自己定义了catch
方法,那么它被rejected
,并不会触发Promise.all()
的catch
方法
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
如果p2
没有自己的catch
方法,就会调用Promise.all()
的catch
方法
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// Error: 报错了
race()
Promise.race()
方法同样是将多个Promise
实例,包装成一个新的Promise
实例
const p = Promise.race([p1,p2,p3])
只要p1,p2,p3
之中有一个实例率先改变状态,p
的状态就跟着改变,率先改变的Promise
实例的返回值则传递给p
的回调函数
const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
allSettled()
Promise.allSettled()
方法接受一组Promise
实例作为参数,包装成一个新的Promise
实例,只有等到所有的这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束
const promises = [
fetch('/api-1'),
fetch('/api-2'),
fetch('/api-3'),
];
await Promise.allSettled(promises);
removeLoadingIndicator();