⭐️ ES2021(ES12)新特性
Promise.any()
接收一个 Promise 可迭代对象(例如数组),只要其中的一个 Promise 实例 Fulfilled,就返回那个已经 Fulfilled 的可迭代对象的成员。如果可迭代对象中没有一个成员状态变更(即所有的 promise
成员都 Rejected),就返回一个 Rejected 状态的 Promise 实例和 AggregateError 类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和 Promise.all()
方法相反。
语法:
Promise.any(values);
类型声明:
interface PromiseConstructor {any<T>(values: (T | PromiseLike<T>)[] | Iterable<T | PromiseLike<T>>): Promise<T>;}interface PromiseLike<T> {then<TResult = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PrimiseLike<TResult1 | TResult2>;}
参数说明:
参数 | 说明 | 类型 |
---|---|---|
values | 可迭代对象,例如数组 | Iterable |
返回值:
这个方法用于返回第一个成功的 promise
,因此只要有一个 promise
成功此方法就会终止,它不会等待其他的 promise
全部完成。
该方法不会像 Promise.all()
会返回一组完成值那样,我们只能得到一个成功值(假设至少有一个 promise
完成)。当我们只需要一个 promise
成功,而不关心是哪一个成功时此方法很有用。
同时,也不像 Promise.race()
总是返回第一个结果值,这个方法返回的时第一个 Fulfilled 的值。这个方法将会忽略掉所有被拒绝的 promise
,知道第一个 promise
成功。
const promiseList = [Promise.reject('Error A'),Promise.reject('Error B'),Promise.resolve('result'),];Promise.any(promiseList).then((value) => {console.log('value:', value);}).catch((err) => {console.log('err:', err);});
Promise.any([]).then((res) => console.log('fulfilled:', res)).catch((e) => {console.log('rejected:', e);// Output: `rejected: AggregateError: All promises were rejected`});
传入的可迭代对象全部为非 Promise 类型值:
const result2 = Promise.any([1, 2, 3]).then((res) => {console.log('fulfilled:', res);// Output: `fulfilled: 1`}).catch((e) => console.log('rejected:', e));
传入的可迭代对象既包含非 Promiose 类型,也包含 Promise 实例:
const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve(2);}, 500);});Promise.any([1, p2, 3]).then((res) => {console.log('fulfilled:', res);// Output: `fulfilled: 1`}).catch((e) => {console.log('rejected:', e);});
来自世界各地的用户访问网站,如果你有多台服务器,则尽量使用响应速度最快的服务器,在这种情况下,可以使用 Promise.any()
方法从最快的服务器接收响应。
function getUser(endpoint) {return fetch(`https://superfire.${endpoint}.com/users`).then((response) => respons.json());}const promises = [getUser('jp'), getUser('uk'), getUser('us'), getUser('au'), getUser('in')];Promise.any(promises).then((value) => {console.log(value);}).catch((err) => {console.log(err);});
在这个例子,我们有一个获取图片并返回 Blob 的函数,我们使用 Promise.any()
来获取一些图片并显示第一张有效的图片(即最先 resolved
的那个 promise
)。
function fetchAndDecode(url) {return fetch(url).then((response) => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);} else {return response.blob();}});}let coffee = fetchAndDecode('coffee.jpg');let tea = fetchAndDecode('tea.jpg');Promise.any([coffee, tea]).then((value) => {let objectURL = URL.createObjectURL(value);let image = document.createElement('img');img.src = objectURL;docuemnt.body.appendChild(image);}).catch((err) => {console.log(e.message);});
MockPromise.any = function (promiseList) {return new Promise((resolve, reject) => {promiseList = Array.isArray(promiseList) ? promiseList : [];let len = promiseList.length;// 用于收集所有 rejectlet errs = [];// 如果传入的是一个空数组,那么就直接返回 AggregateErrorif (len === 0) return reject(new AggregateError('All promise were rejected'));promiseList.forEach((promise) => {promise.then((value) => {resolve(value);},(err) => {len--;errs.push(err);if (len === 0) {reject(new AggregateError(errs));}});});});};