Promise.all 解決多個請求並發執行,並且有錯誤還能按順序執行並輸出。


要解決這個問題,首先要知道Promise.all是什么?

  • Promise.all() 它接收一個promise對象組成的數組作為參數,並返回一個新的promise對象。

  • 當數組中所有的對象都resolve時,新對象狀態變為fulfilled,所有對象的resolve的value依次添加組成一個新的數組,並以新的數組作為新對象resolve的value。

  • 當數組中有一個對象reject時,新對象狀態變為rejected,並以當前對象reject的reason作為新對象reject的reason。

我們用setTimeout來模擬請求,數據data = [500, 400, 300, 200, 100]既是每個請求返回的數據也是每個請求所需的時間。

如果是繼發請求(一個請求結束后再請求后一個),那么應該是按順序打印,理論上所有請求的總時間等於每個請求所花時間之和,約等於1500ms;如果是並發請求(假設請求數不會太多,不超過限制),順序是按時間從小到大打印,理論上所有請求的總時間等於最長的那個時間,約等於500ms

// 模擬請求
function request(param) {
return new Promise(resolve => {
    setTimeout(() => {
console.log(param)
       resolve()
    }, param)
  })
}
const items = [500, 400, 300, 200, 100]

使用Promise.all可以並發執行,並知道請求結束。

(() => {
Promise.all(items.map(request)).then(res => {
console.log('end')
  })
})()
// 輸出:100, 200, 300, 400, 500, end

但是由Promise.all的定義知道,當其中一個出錯時,就不會resolve返回值。
模擬一個出錯的情況

const items = [500, 400, 300, 200, 100]
function request(param) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (param === 200) {
      // console.log(param, ' failed')
        return reject({ 
          status: 'error',
          data: param
        })
      }
// console.log(param, ' success')
    resolve({
      status: 'success',
      data: param
      })
    }, param)
  })
}

出錯時,在使用剛剛那個Promise.all時就會打印

(() => {
Promise.all(items.map(request))
    .then(res => {
console.log(res)
    })
    .catch (err => {
console.log(err)
    })
    .finally(res => {
console.log('end', res)
    })
})()
// 輸出 {status: "error", data: 200}, end, undefined

上面的輸出可以看出,如果有錯誤,則不會進入then,而是進入catch,然后進入finally,但是finally不接受參數,只告訴你結束了。如果把上面模擬請求的console.log(...)注釋去掉,還會發現finally是在catch結束后就執行了,而200后面的請求還未結束。

接下來我們改造下模擬請求,在請求出錯后就catch錯誤

使用catch捕獲錯誤,然后就能再執行catch后面的正確函數,不使用catch捕獲錯誤,一旦出錯,就會停止繼續執行正確函數。

const items = [500, 400, 300, 200, 100]

// 請求出錯時,catch錯誤就可以。當出錯時,仍能按順序執行並輸出。

function request(param) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (param === 200) {
      // console.log(param, ' failed')
        return reject({ 
          status: 'error',
          data: param
        })
      }
// console.log(param, ' success')
    resolve({
      status: 'success',
      data: param
      })
    }, param)
  }).catch(err => err)
}
// 輸出 [{…}, {…}, {…}, {stauts: 'error', data: 200}, {…}], end

這樣就解決了我們的問題了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM