您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“怎么有效的處理Promise并發”,內容詳細,步驟清晰,細節處理妥當,希望這篇“怎么有效的處理Promise并發”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
Promise.all 大家應該是比較熟悉的,Promise.all
方法接收一個promise
的iterable
類型,如果所有傳入的promise
都變成完成狀態,Promise.all
返回的Promise異步的變為完成。如果傳入的promise
中有一個失敗(rejected
),Promise.all
將失敗的結果給失敗狀態的回調函數,而不管其他promise
是否完成。 我們可以如下實現剛才的代碼
async function init() { const [user, info] = await Promise.all([ getUser(), getInfo() ]) console.log('init', user, info) }
現在這種方式,如果我們之前每個請求都需要1秒,一共需要2秒,那么現在兩個同時執行只需要1秒就完成了!但是這樣也有一個問題:我們并沒有考慮報錯問題。你可能會認為,這個很簡單,把代碼放在一個try...cahtch
中不就可以了,就像這樣:
async function init() { try { const [user, info] = await Promise.all([ getUser(), getInfo() ]) console.log('init ==== ', user, info) } catch(err) { console.log('err', err); } }
但是,這樣的話會有一個問題,就像這樣:
function getUser() { return new Promise((resolve, reject) => { setTimeout(() => { reject('user reject') }, 500); }) } function getInfo() { return new Promise((resolve, reject) => { setTimeout(() => { reject('info reject') }, 1000); }) } // 輸出 err user reject
由于getUser
優先完成并出現錯誤,此時觸發了catch
,而當getInfo
再次完成并出現錯誤時,將不會觸發catch
。因為catch
代碼已經運行,函數已經完成。 那么,要怎么做呢?接下來,我們就講講應該如何處理報錯問題。
解決方式是,給Promise.all
中的每個函數加上catch
,如下:
function handle(err) { console.log('err', err) } function onReject(err) { handle(err); return new Error(err); } async function init() { const [user, info] = await Promise.all([ getUser().catch(onReject), getInfo().catch(onReject) ]) console.log('init', user instanceof Error, info instanceof Error) // init true true }
這樣,我們在onReject
函數中處理錯誤,并返回這個錯誤。所以現在我們生成的user
和info
要么是Error
要么是我們期望的效果,而Error
我們可以用instanceof
檢查它。
解決并發我們還可以使用 Promise.allSettled ,我們會得到一個包含每個Promise
結果的值或錯誤信息。
接下來,我們來使用一下,代碼如下:
async function init() { const [userStatus, infoStatus] = await Promise.allSettled([ getUser(), getInfo() ]) console.log('info', userStatus, infoStatus) }
現在,我們可以得到這樣的數據:
結果對象有3個屬性:
status: fulfilled
或 rejected
value: 僅在status
為fulfilled
時出現,為Promise
為resolve
返回的值
reason: 僅在status
為rejected
時出現,為Promise
被reject
時返回的值
因此,我們可以讀取到每個Promise
的狀態,并單獨處理每個錯誤而不會遺漏任何的信息。
Promise.race方法可接受一個可迭代的promise
返回一個promise
,一旦迭代器中某個promise
解決或拒絕,返回的promise
就會resolve
或reject
。
我們可以這樣實現一個簡單的超時功能,代碼如下:
function getUser() { return new Promise((resolve) => { setTimeout(() => { resolve('user resolve') }, 5100); }) } async function init() { // Race to see which Promise completes first const racePromise = Promise.race([ getUser(), new Promise((resolve, reject) => // Time out after 5 seconds setTimeout(() => reject(new Error('Timeout')), 5000) ) ]) try { const result = await racePromise console.log('result', result) } catch (err) { console.log('err', err) // Timed out! } }
注意,通常情況下,如果有超時,那么你需要盡量的取消未完成的待處理任務。
另外,最好還是處理所有promise
的reject
:
const racePromise = Promise.race([ getUser().catch(onReject), // xxx ])
Promise.any 等待任何一個promise
成功則為成功,只有全部的promise
都被reject
,才會返回reject
。通常我們可以使用Promise.any
來實現,當一個promise
先完成后,取消其他的promise
,不過要注意的是,我們并不總是同時要處理多個數據,只是因為我們可以做到,所以要謹慎的使用它。
通常,我們不想出現未被處理的reject
,所以,我們應該這樣寫:
const anyPromise = Promise.any([ getUser().catch(onReject), getInfo().catch(onReject) ])
讀到這里,這篇“怎么有效的處理Promise并發”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。