Promise.any 的作用,如何自己實(shí)現(xiàn)一個(gè) Promise.any
本文轉(zhuǎn)載自微信公眾號「三分鐘學(xué)前端」,作者sisterAn。轉(zhuǎn)載本文請聯(lián)系三分鐘學(xué)前端公眾號。
引言
本文從五個(gè)方面介紹 Promise.any :
- Promise.any 的作用
- Promise.any 應(yīng)用場景
- Promise.any vs Promise.all
- Promise.any vs Promise.race
- 手寫 Promise.any 實(shí)現(xiàn)
下面正文開始
Promise.any
Promise.any() 是 ES2021 新增的特性,它接收一個(gè) Promise 可迭代對象(例如數(shù)組),
- 只要其中的一個(gè) promise 成功,就返回那個(gè)已經(jīng)成功的 promise
- 如果可迭代對象中沒有一個(gè) promise 成功(即所有的 promises 都失敗/拒絕),就返回一個(gè)失敗的 promise 和 AggregateError 類型的實(shí)例,它是 Error 的一個(gè)子類,用于把單一的錯(cuò)誤集合在一起
- const promises = [
- Promise.reject('ERROR A'),
- Promise.reject('ERROR B'),
- Promise.resolve('result'),
- ]
- Promise.any(promises).then((value) => {
- console.log('value: ', value)
- }).catch((err) => {
- console.log('err: ', err)
- })
- // value: result
如果所有傳入的 promises 都失?。?/p>
- const promises = [
- Promise.reject('ERROR A'),
- Promise.reject('ERROR B'),
- Promise.reject('ERROR C'),
- ]
- Promise.any(promises).then((value) => {
- console.log('value:', value)
- }).catch((err) => {
- console.log('err:', err)
- console.log(err.message)
- console.log(err.name)
- console.log(err.errors)
- })
- // err:AggregateError: All promises were rejected
- // All promises were rejected
- // AggregateError
- // ["ERROR A", "ERROR B", "ERROR C"]
Promise.any 應(yīng)用場景
- 從最快的服務(wù)器檢索資源
來自世界各地的用戶訪問網(wǎng)站,如果你有多臺服務(wù)器,則盡量使用響應(yīng)速度最快的服務(wù)器,在這種情況下,可以使用 Promise.any() 方法從最快的服務(wù)器接收響應(yīng)
- function getUser(endpoint) {
- return fetch(`https://superfire.${endpoint}.com/users`)
- .then(response => response.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);
- })
- 顯示第一張已加載的圖片(來自MDN)
在這個(gè)例子,我們有一個(gè)獲取圖片并返回 blob 的函數(shù),我們使用 Promise.any() 來獲取一些圖片并顯示第一張有效的圖片(即最先 resolved 的那個(gè) 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');
- image.src = objectURL;
- document.body.appendChild(image);
- })
- .catch(e => {
- console.log(e.message);
- });
Promise.any vs Promise.all
Promise.any() 和 Promise.all() 從返回結(jié)果來看,它們 彼此相反 :
- Promise.all() :任意一個(gè) promise 被 reject ,就會立即被 reject ,并且 reject 的是第一個(gè)拋出的錯(cuò)誤信息,只有所有的 promise 都 resolve 時(shí)才會 resolve 所有的結(jié)果
- Promise.any() :任意一個(gè) promise 被 resolve ,就會立即被 resolve ,并且 resolve 的是第一個(gè)正確結(jié)果,只有所有的 promise 都 reject 時(shí)才會 reject 所有的失敗信息
另外,它們又有不同的 重點(diǎn) :
- Promise.all() 對所有實(shí)現(xiàn)都感興趣。相反的情況(至少一個(gè)拒絕)導(dǎo)致拒絕。
- Promise.any() 對第一個(gè)實(shí)現(xiàn)感興趣。相反的情況(所有拒絕)導(dǎo)致拒絕。
Promise.any vs Promise.race
Promise.any() 和 Promise.race() 的 關(guān)注點(diǎn) 不一樣:
- Promise.any() :關(guān)注于 Promise 是否已經(jīng)解決
- Promise.race() :主要關(guān)注 Promise 是否已經(jīng)解決,無論它是被解決還是被拒絕
手寫 Promise.any 實(shí)現(xiàn)
Promise.any 只要傳入的 promise 有一個(gè)是 fullfilled 則立即 resolve 出去,否則將所有 reject 結(jié)果收集起來并返回 AggregateError
- MyPromise.all = function(promises){
- return new Promise((resolve,reject)=>{
- promises = Array.isArray(promises) ? promises : []
- let len = promises.length
- // 用于收集所有 reject
- let errs = []
- // 如果傳入的是一個(gè)空數(shù)組,那么就直接返回 AggregateError
- if(len === 0) return reject(new AggregateError('All promises were rejected'))
- promises.forEach((promise)=>{
- promise.then(value=>{
- resolve(value)
- },err=>{
- len--
- errs.push(err)
- if(len === 0){
- reject(new AggregateError(errs))
- }
- })
- })
- })
- }
來自:https://github.com/sisterAn/blog