Promise-any 的作用,如何自己實現一個 Promise-any
引言
本文從五個方面介紹 Promise.any
:
-
Promise.any
的作用 -
Promise.any
應用場景 -
Promise.any
vsPromise.all
-
Promise.any
vsPromise.race
-
手寫
Promise.any
實現
下面正文開始👇
Promise.any
Promise.any()
是 ES2021 新增的特性,它接收一個 Promise
可迭代對象(例如數組),
-
只要其中的一個
promise
成功,就返回那個已經成功的promise
-
如果可迭代對象中沒有一個
promise
成功(即所有的promises
都失敗 / 拒絕),就返回一個失敗的promise
和AggregateError
類型的實例,它是Error
的一個子類,用於把單一的錯誤集合在一起
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
都失敗:
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 應用場景
-
從最快的服務器檢索資源
來自世界各地的用戶訪問網站,如果你有多臺服務器,則儘量使用響應速度最快的服務器,在這種情況下,可以使用
Promise.any()
方法從最快的服務器接收響應
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)
在這個例子,我們有一個獲取圖片並返回
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');
image.src = objectURL;
document.body.appendChild(image);
})
.catch(e => {
console.log(e.message);
});
Promise.any vs Promise.all
Promise.any()
和 Promise.all()
從返回結果來看,它們 彼此相反 :
-
Promise.all()
:任意一個promise
被reject
,就會立即被reject
,並且reject
的是第一個拋出的錯誤信息,只有所有的promise
都resolve
時纔會resolve
所有的結果 -
Promise.any()
:任意一個promise
被resolve
,就會立即被resolve
,並且resolve
的是第一個正確結果,只有所有的promise
都reject
時纔會reject
所有的失敗信息
另外,它們又有不同的 重點 :
-
Promise.all()
對所有實現都感興趣。相反的情況(至少一個拒絕)導致拒絕。 -
Promise.any()
對第一個實現感興趣。相反的情況(所有拒絕)導致拒絕。
Promise.any vs Promise.race
Promise.any()
和 Promise.race()
的 關注點 不一樣:
-
Promise.any()
:關注於Promise
是否已經解決 -
Promise.race()
:主要關注Promise
是否已經解決,無論它是被解決還是被拒絕
手寫 Promise.any 實現
Promise.any
只要傳入的 promise
有一個是 fullfilled
則立即 resolve
出去,否則將所有 reject
結果收集起來並返回 AggregateError
MyPromise.any = function(promises){
return new Promise((resolve,reject)=>{
promises = Array.isArray(promises) ? promises : []
let len = promises.length
// 用於收集所有 reject
let errs = []
// 如果傳入的是一個空數組,那麼就直接返回 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
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/sSq0RHW36-I-KKqkBjBKYw