Promise的实例方法拓展
Promise.all()
:方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
Promise.allSettled()
:用来确定一组异步操作是否都结束了(不管成功或失败)。所以,它的名字叫做”Settled“,包含了”fulfilled“和”rejected“两种情况。
Promise.any()
:ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。
Promise.race()
:方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
一、Promise.all()
介绍:
Promise.all()
方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入。并且只返回一个Promise实例, 那个输入的所有 promise 的 resolve 回调的结果是一个数组。
这个Promise的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。
它的 reject 回调执行是,只要任何一个输入的 promise 的 reject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是第一个抛出的错误信息。
用法示例:
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
//结果:
//reject
//Promise {<fulfilled>: undefined}
只有p1、p2、p3、p4、p5的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
只要p1、p2、p3、p4、p5之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
应用场景:
当我们需要所有异步任务都同时进行并且完成时可以使用.all方法
all是比较常用的一个方法,比如当我们的页面中需要多个接口同时在页面进入时请求数据,这时就可以使用all方法把多个 axios 合并后一起发送请求,并加入loading加载让用户等待。
面试题:
必须当三个axios请求都成功时,才能发送第四个请求,用promise实现?
我们可以用 .all方法实现:
let a = axios.get("http://xxxa")
let b = axios.get("http://xxxb")
let c = axios.get("http://xxxc")
let d = axios.get("http://xxxd")
Promise.all([a, b, c]).then(resx => {
console.log('resx:',resx);
d.then(resy => console.log('resy:',resy))
},err => console.log(err))
/*结果:
resx: (3) [{…}, {…}, {…}]
resy:{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
*/
二、Promise.allSettled()
介绍:
Promise.allSettled()
方法返回一个在所有给定的 promise 都已经fulfilled或rejected后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。
当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。
相比之下,Promise.all() 更适合彼此相互依赖或者在其中任何一个reject时立即结束。
用法示例:
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
});
Promise.allSettled([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
//结果:
//Promise {<pending>}
//(5) [{…}, {…}, {…}, {…}, {…}]
//0: {status: "fulfilled", value: "one"}
//1: {status: "fulfilled", value: "two"}
//2: {status: "fulfilled", value: "three"}
//3: {status: "fulfilled", value: "four"}
//4: {status: "rejected", reason: "reject"}
//length: 5
//[[Prototype]]: Array(0)
一旦所指定的 promises 集合中每一个 promise 已经完成,无论是成功的达成或被拒绝,未决议的 Promise将被异步完成。那时,所返回的 promise 的处理器将传入一个数组作为输入,该数组包含原始 promises 集中每个 promise 的结果。
对于每个结果对象,都有一个 status 字符串。如果它的值为 fulfilled,则结果对象上存在一个 value 。如果值为 rejected,则存在一个 reason 。value(或 reason )反映了每个 promise 决议(或拒绝)的值。
可以发现和all相比,allSettled在其中一个promise返回错误时还可以继续等待结果。并且不管内部的计时器定时多少毫秒,它都会等所有结果返回后按照传参传入的顺序返回promise结果。
应用场景:
比如我们用户在页面上面同时填了3干个独立的表单,这三个表单分三个接口提交到后端,三个接口独立,没有顺序依赖,这个时候我们需要等到请求全部完成后给与用户提示表单提交的情况。
面试题:
共有四个接口,第一个接口是崩溃的,但是需要返回所有接口的结果。
这一题如果使用 all,那么会直接抛出错误,所以必须使用allSettled方法请求数据
let a = axios.get("http://xxxa")
let b = axios.get("http://xxxb")
let c = axios.get("http://xxxc")
let d = axios.get("http://xxxd")
Promise.allSettled([a, b, c,d]).then(resx => {
console.log('resx:',resx);
},err => console.log(err))
/*结果:
第一个接口请求结果是错误的
(4) [{…}, {…}, {…}, {…}]
0: {status: "rejected", reason: Error:log…}
1: {status: "fulfilled", value: {…}}
2: {status: "fulfilled", value: {…}}
3: {status: "fulfilled", value: {…}}
*/
三、Promise.any()
介绍:
Promise.any()
接收一个由 Promise 所组成的可迭代 iterable对象,该方法会返回一个新的 promise,一旦可迭代对象内的任意一个 promise 变成了兑现状态,那么由该方法所返回的 promise 就会变成兑现状态,并且它的兑现值就是可迭代对象内的首先兑现的 promise 的兑现值。
如果可迭代对象内的 promise 最终都没有兑现(即所有 promise 都被拒绝了),那么该方法所返回的 promise 就会变成拒绝状态,并且它的拒因会是一个 AggregateError 实例,这是 Error 的子类,用于把单一的错误集合在一起。
用法:
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
});
Promise.any([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
//结果:
//Promise {<pending>}
// one
只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
Promise.any()
跟Promise.race()
方法很像,只有一点不同,就是Promise.any()
不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。
应用场景:
和race
一样,当我们需要处理多个异步任务返回最快的成功的结果时可以使用 any
面试题:
共有四个个接口,要求只处理第一个成功执行的函数。
let a = axios.get("http://xxxa")
let b = axios.get("http://xxxb")
let c = axios.get("http://xxxc")
let d = axios.get("http://xxxd")
Promise.any([a,b,c,d]).then(res => {
console.log('result',res);
}, error => {
console.log('error',err);
})
/*
结果:
返回状态成功的内容
result:{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
*/
四、Promise.race()
介绍:
Promise.race(iterable)
方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。
用法:
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
});
Promise.race([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
//结果:
//reject
//Promise {<fulfilled>: undefined}
race
函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
如果传的迭代是空的,则返回的 promise 将永远等待。
如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race
将解析为迭代中找到的第一个值。
可以发现race
在遇到立即执行的reject
时并没有像any
一样继续等待resolve
的返回,而是直接返回了reject的内容。
应用场景:
和any一样,当我们需要处理多个异步任务但是不要求返回的内容是正确和错误时返回最快的结果时可以使用 race。
面试题:
共有四个接口,任何一个接口先完成就可以,无论是成功还是报错。
let a = axios.get("http://xxxa")
let b = axios.get("http://xxxb")
let c = axios.get("http://xxxc")
let d = axios.get("http://xxxd")
Promise.any([a,b,c,d]).then(res => {
console.log('result',res);
}, error => {
console.log('error',err);
})
/*
结果:
返回状态成功切反应最快的接口数据
result:{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
*/