掌握 Promise 的邏輯方法


Promise 是 ES2015 新增的對象

Promise 對象有幾個組合方法,可以將多個承諾合並成一個進行處理

分別是 Promise.all, Promise.race, Promise.allSettled, Promise.any

這些方法都可以接收一組承諾,返回一個新的承諾

Promise.all(values)

其中參數 values 是一個可迭代對象,比如數組

在后文中我都使用詞語“成功”表示承諾 resolve,“失敗”表示承諾 reject

Promise.all

Promise.all 方法返回的承諾會等到參數中所有的承諾都成功之后才會成功,只要其中有一個失敗了則返回的承諾也會立即失敗,不會等到那些還掛起的承諾有結果

Promise.all

Promise.all 方法可以用來處理那些缺一不可的邏輯

示例:同時發出多個請求都成功后才能進行下一步

const coffee = fetch('/coffee')
const tea = fetch('/tea')
const me = fetch('/me')

try {
  // 我全都要
  const res = await Promise.all([coffee, tea, me])
  // res 是個數組
} catch (err) {
  // 至少有一個請求失敗了
}

Promise.all 方法 resolve 的結果是一個數組

參數中的承諾對象並不會按順序解析,但是結果數組中的順序與傳遞順序相同

Promise.race

Promise.race 方法返回參數中最快的那個承諾,如果最快的那個承諾成功則返回的承諾也會成功,否則就是失敗,不會等待那些還掛起的承諾有結果

Promise.race

示例:給一個復雜任務設定一個超時時間

// 設置一個定時器,時間到了就 reject 一個承諾
const timeout = new Promise((resolve, reject) => {
  setTimeout(reject, 3000)
})

// 這是一個復雜任務,可能是輪詢,也可能是多個異步請求
const missions = new Promise((resolve, reject) => { ... })

try {
  const res = await Promise.race([timeout, missions])
  // missions 任務在 3 秒內成功了
} catch () {
  // 時間超過 3 秒了或者任務失敗了
}

Promise.allSettled

Promise.allSettled 方法返回的承諾對象會等到參數中所有的承諾對象都完成后才成功,無論怎樣該方法返回的承諾都不會失敗

Promise.allSettled

和 Promise.all 方法的區別

Promise.all 方法需要參數中的所有承諾都成功

而 Promise.allSettled 對參數中的承諾是成功還是失敗並不關心,只要有結果就行

示例:一次性上傳多個文件,其中上傳成功和上傳失敗的互不影響,在一輪上傳任務完成之后,可以篩選出那些上傳失敗的重新上傳

// 這是一個上傳文件的方法,返回一個承諾
const upload = file => {
  const formData = new FormData()
  formData.append('file', file)
  return fetch('/upload', {
    method: 'POST',
    body: formData
  })
}

// 在文件選擇框的 change 事件處理程序中執行上傳任務
document.querySelector('input[type="file"]').addEventListener('change', function(e) {
  if (!e.target.value) return // 如果啥都沒有選
  const files = e.target.files
  // 遍歷所有文件並上傳返回承諾數組
  const promises = files.map(file => upload(file))

  // 數組正好可以傳遞給 allSettled 方法
  const res = await Promise.allSettled(promises)
  // 全部上傳任務都完成了,挑選出上傳失敗的重新上傳
})

該方法是 ES2020 新添加的方法

Promise.any

Promise.any 方法返回一組承諾中最快成功的那個承諾,如果參數中所有承諾都失敗了,那么返回的承諾也失敗

Promise.any

和 Promise.race 方法的區別

Promise.race 返回參數中最快的那個承諾,無論它是成功還是失敗

而 Promise.any 關注的是參數中最快同時還必須成功的那個承諾

和 Promise.all 方法的區別

Promise.any 和 Promise.all 是完全相反的

Promise.any 參數中全部承諾都失敗了才會失敗,Promise.all 參數中全部承諾都成功了才會成功

Promise.any 參數中一旦有一個承諾成功了返回的新承諾就會成功,Promise.all 參數中一旦有一個承諾失敗了返回的新承諾就會失敗

示例:同時加載一組圖片,但是我們只需要用到其中的一張,就可以用 Promise.any 方法挑選出最先加載成功的那張圖片

// 這是一個請求圖片的方法,成功則返回圖片
const fetchImg = async (url) => {
  return fetch(url).then(res => {
    if (!res.ok) {
      throw new Error('HTTP error!')
    } else {
      return res.blob()
    }
  })
}

cosnt img1 = fetchImg('/1.png')
const img2 = fetchImg('/2.png')

try {
  const res = await Promise.any([img1, img2])
  // 只要有一個成功就可以
  const url = URL.createObjectURL(res)
  const img = document.createElement('img')
  img.src = url
  document.body.appendChild(img)
} catch () {
  // 一個都沒加載成功 QAQ
}

該方法還處於草案中,目前最新的 Chrome, Firefox, Safari 支持

以上所有方法要么環境本身已經實現,要么在 core.js 中有實現,都可以放心食用


免責聲明!

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



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