溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么有效的處理Promise并發(fā)

發(fā)布時間:2023-04-19 15:54:14 來源:億速云 閱讀:116 作者:iii 欄目:開發(fā)技術

本文小編為大家詳細介紹“怎么有效的處理Promise并發(fā)”,內容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“怎么有效的處理Promise并發(fā)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

    Promise.all

    如何實現(xiàn)

    Promise.all 大家應該是比較熟悉的,Promise.all方法接收一個promiseiterable類型,如果所有傳入的promise都變成完成狀態(tài),Promise.all返回的Promise異步的變?yōu)橥瓿?。如果傳入?code>promise中有一個失敗(rejected),Promise.all將失敗的結果給失敗狀態(tài)的回調函數,而不管其他promise是否完成。 我們可以如下實現(xiàn)剛才的代碼

    async function init() {
      const [user, info] = await Promise.all([
        getUser(),
        getInfo()
      ])
      console.log('init', user, info)
    }

    現(xiàn)在這種方式,如果我們之前每個請求都需要1秒,一共需要2秒,那么現(xiàn)在兩個同時執(zhí)行只需要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優(yōu)先完成并出現(xiàn)錯誤,此時觸發(fā)了catch,而當getInfo再次完成并出現(xiàn)錯誤時,將不會觸發(fā)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函數中處理錯誤,并返回這個錯誤。所以現(xiàn)在我們生成的userinfo要么是Error要么是我們期望的效果,而Error我們可以用instanceof檢查它。

    Promise.allSettled

    解決并發(fā)我們還可以使用 Promise.allSettled ,我們會得到一個包含每個Promise結果的值或錯誤信息。

    如何實現(xiàn)

    接下來,我們來使用一下,代碼如下:

    async function init() {
      const [userStatus, infoStatus] = await Promise.allSettled([
        getUser(),
        getInfo()
      ])
      console.log('info', userStatus, infoStatus)
    }

    現(xiàn)在,我們可以得到這樣的數據:

    怎么有效的處理Promise并發(fā)

    結果對象有3個屬性:

    • status: fulfilledrejected

    • value: 僅在statusfulfilled時出現(xiàn),為Promiseresolve返回的值

    • reason: 僅在statusrejected時出現(xiàn),為Promisereject時返回的值

    因此,我們可以讀取到每個Promise的狀態(tài),并單獨處理每個錯誤而不會遺漏任何的信息。

    最后兩個技巧

    Promise.race

    Promise.race方法可接受一個可迭代的promise返回一個promise,一旦迭代器中某個promise解決或拒絕,返回的promise就會resolvereject。

    我們可以這樣實現(xiàn)一個簡單的超時功能,代碼如下:

    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!
      }
    }

    注意,通常情況下,如果有超時,那么你需要盡量的取消未完成的待處理任務。

    另外,最好還是處理所有promisereject

    const racePromise = Promise.race([
        getUser().catch(onReject),
        // xxx
      ])

    Promise.any

    Promise.any 等待任何一個promise成功則為成功,只有全部的promise都被reject,才會返回reject。通常我們可以使用Promise.any來實現(xiàn),當一個promise先完成后,取消其他的promise,不過要注意的是,我們并不總是同時要處理多個數據,只是因為我們可以做到,所以要謹慎的使用它。

    通常,我們不想出現(xiàn)未被處理的reject,所以,我們應該這樣寫:

    const anyPromise = Promise.any([
        getUser().catch(onReject),
        getInfo().catch(onReject)
    ])

    讀到這里,這篇“怎么有效的處理Promise并發(fā)”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業(yè)資訊頻道。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI