Promise 是異步編程的一種解決方案,比傳統的回呼函式或事件更合理和更靈活,
Promise 方法
Promise的原型方法:then/catch/finally,這三種方法很常用,then用于處理Promise轉為fulfilled狀態時的代碼,catch用于處理Promise轉為rejected狀態時的代碼(當然then的第二個引數也可處理rejected狀態),而finally用于不管Promise狀態怎樣轉換都會最終執行的代碼,
promise的then方法的第二個引數和catch方法都可以處理rejected狀態,但它們之間有一些區別:
then的第二個引數只能處理當前的promise,而catch方法可以處理任意位置的rejected狀態,所以,如果多個then方法鏈式呼叫中有多個rejected狀態,可以在最后使用一個catch方法來處理,
then的第二個引數和catch方法的回傳值不同,then的第二個引數回傳的是一個新的promise物件,而catch方法回傳的是一個值或一個新的promise物件,如果回傳的是一個值,則會被自動包裝成一個resolved狀態的promise,
catch方法比then的第二個引數更簡潔,更易讀,因為catch方法只處理rejected狀態,而then方法需要在第一個引數中同時處理resolved和rejected狀態,
Promise的靜態方法: Promise.all、Promise.allSettled、Promise.any、Promise.race、Promise.resolve、Promise.reject,
Promise 靜態方法
Promise.resolve和Promise.reject用于一開始就創建 fulfilled或rejected狀態的Promise,其他的靜態方法傳參是Promise實體陣列,差異在于處理實體陣列的方式和結果,
Promise.all
并行執行多個Promise物件,并在所有Promise物件都成功時回傳一個新的Promise物件,其resolve值為一個包含所有Promise結果的陣列,如果其中一個Promise物件失敗,則回傳一個reject的Promise物件,其值為第一個失敗的Promise的reject值,
;(async () => {
const promise1 = Promise.resolve('Hello')
const promise2 = 42
// const promise2 = Promise.reject('Error')
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'Goodbye')
})
// const promise4 = Promise.reject('Error2')
try {
const result = await Promise.all([promise1, promise2, promise3])
// 成功輸出:[ 'Hello', 42, 'Goodbye' ]
console.log(result)
} catch (e) {
// 失敗輸出:Error
console.log(e)
}
})()
Promise.allSettled
并行執行多個Promise物件,回傳一個新的Promise物件(狀態一定是fulfilled),其resolve值為一個包含所有Promise結果的陣列,其中每個元素都是物件,包含Promise物件的狀態和結果,
;(async () => {
const promise1 = Promise.resolve('Hello')
const promise2 = 42
// const promise2 = Promise.reject('Error')
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'Goodbye')
})
// const promise4 = Promise.reject('Error2')
try {
const result = await Promise.allSettled([promise1, promise2, promise3])
// 成功輸出:
// [
// { status: 'fulfilled', value: 'Hello' },
// { status: 'fulfilled', value: 42 },
// { status: 'fulfilled', value: 'Goodbye' }
// ]
console.log(result)
// 失敗輸出:
// [
// { status: 'fulfilled', value: 'Hello' },
// { status: 'rejected', reason: 'Error' },
// { status: 'fulfilled', value: 'Goodbye' }
// ]
} catch(e) {
// 不會執行
console.log('error:', e)
}
Promise.allSettled([promise1, promise2, promise3]).then((result) => {
// 成功輸出:
// [
// { status: 'fulfilled', value: 'Hello' },
// { status: 'fulfilled', value: 42 },
// { status: 'fulfilled', value: 'Goodbye' }
// ]
console.log(result)
// 失敗輸出:
// [
// { status: 'fulfilled', value: 'Hello' },
// { status: 'rejected', reason: 'Error' },
// { status: 'fulfilled', value: 'Goodbye' }
// ]
})
})()
Promise.all和Promise.allSettled的區別:
- Promise.all方法回傳的一個Promise物件狀態將取決于所有Promise物件的狀態,如果其中有任何一個Promise物件被rejected了,那么這個新的Promise物件也會被rejected,并且它的值為第一個被rejected的那個Promise物件的值,
- Promise.allSettled方法回傳的一個Promise物件狀態一定是fulfilled,這個回傳的Promise物件的值是一個陣列,陣列中包含了所有Promise物件的狀態和值資訊,即便其中有任何一個Promise物件被rejected了,也不會影響這個新的Promise物件的狀態,
- 錯誤處理方面,Promise.all只能捕獲處理第一個錯誤狀態,如果需要處理所有狀態需要改造(如:每個promise設定catch處理、同步請求/異步等待)或者使用 Promise.allSettled,具體需要怎么做看自己的需求
Promise.any
并行執行多個Promise物件,并回傳一個新的Promise物件,其resolve值為第一個成功的Promise物件的resolve值,如果所有Promise物件都失敗,則回傳一個reject的Promise物件,其值為一個AggregateError物件,其中包含所有Promise物件的reject值,
const promise1 = Promise.reject("error1")
const promise2 = Promise.reject("error2")
const promise3 = Promise.resolve("success")
// const promise3 = Promise.reject("error3")
Promise.any([promise1, promise2, promise3]).then((value) => {
// 成功輸出:success
console.log(value)
}).catch((error) => {
// 失敗輸出:
// [AggregateError: All promises were rejected] {
// [errors]: [ 'error1', 'error2', 'error3' ]
// }
console.log(error)
})
Promise.race
并行執行多個Promise物件,并回傳一個新的Promise物件,其resolve值為第一個完成的Promise物件的resolve值,如果所有Promise物件都失敗,則回傳一個reject的Promise物件,其值為第一個失敗的Promise的reject值,
const promise1 = Promise.reject("error1")
const promise2 = Promise.reject("error2")
const promise3 = Promise.resolve("success")
// const promise3 = Promise.reject("error3")
Promise.race([promise1, promise2, promise3]).then((value) => {
// 成功輸出:error1
console.log(value)
}).catch((error) => {
// 失敗輸出:error1
console.log(error)
})
Promise.race和Promise.any的區別:
Promise.race會在其中任意一個Promise物件狀態改變(即fulfilled或rejected)時立即回傳結果,而Promise.any只會在其中任意一個Promise物件fulfilled時回傳結果,
當所有Promise物件都被rejected時,Promise.race會回傳被rejected的Promise物件的結果,而Promise.any會拋出AggregateError例外,
如果Promise.race傳入的引數是空陣列,它會一直處于pending狀態,而Promise.any會立即拋出AggregateError例外,(另外:Promise.all和Promise.allSettled回傳fulfilled狀態)
使用Promise實作站點預檢
這是前幾天實作的站點預檢:判斷所有網站鏈接是否有效,并回傳測驗的結果,思路:通過get請求測驗,考慮請求之間沒有關聯、錯誤處理方面最終選擇Promise.allSettled,代碼如下:
// 實作 對多個網站鏈接預檢,判定網站鏈接是否有效
import { get } from 'https'
import { get as getHttp } from 'http'
import { URL } from 'url'
import { ATagSites } from '@/type'
export const detectSitesValid = (allSites: ATagSites[]) => {
// 遍歷 allSites 陣列,獲取所有網站的鏈接
const sites: { name: string; url: string }[] = []
allSites.forEach((aTagSites) => {
aTagSites.sites.forEach((site) => {
sites.push({
name: site.name,
url: site.link
})
})
})
// 存盤所有網站的請求
const fetchRequests: Promise<string>[] = []
// 存盤請求結果
const fetchResults: string[] = []
// 遍歷所有網站,發起請求
sites.forEach((site) => {
const { name, url } = site
const { protocol } = new URL(url)
const request = protocol === 'https:' ? get : getHttp
fetchRequests.push(
new Promise((resolve, reject) => {
request(
{
hostname: new URL(url).hostname,
path: new URL(url).pathname,
method: 'GET',
timeout: 30000
},
(res) => {
const { statusCode, statusMessage } = res
fetchResults.push(`${name}, ${url}, ${statusCode || 200}, ${statusMessage || 'OK'}`)
resolve('ok')
}
).on('error', (err) => {
const { message } = err
fetchResults.push(`${name}, ${url}, ${0}, ${message}`)
resolve('error')
})
})
)
})
return Promise.allSettled(fetchRequests)
}
參考
- Promise.all和promise.allSettled的用法,promise.all的錯誤捕獲方法
- Promise 的實體方法和靜態方法有哪些,如何手動實作?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/550043.html
標籤:其他
上一篇:由 Base64 展開的知識探討
