javascript異步之Promise.all()、Promise.race()、Promise.finally()

同期異步系列文章推薦
談一談javascript異步
javascript異步中的回調
javascript異步與promise
javascript異步之Promise.resolve()、Promise.reject()
javascript異步之Promise then和catch
javascript異步之async(一)
javascript異步之async(二)
javascript異步實戰
javascript異步總結歸檔

今天我們繼續討論promise
網絡上關於PromiseAPI使用的文章多如牛毛,爲了保持javascript異步系列文章的完整性,現在對promise的API進行簡單全面的介紹

準備工作

我在easy-mock添加了三個接口,備用

依然使用axios進行ajax請求

Promise.all()

Promise.all()有點像“並行”
我們看一個栗子

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>promise</title>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>

<body>
  <script>
    {
      const p1 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1')
        .then(({
          data
        }) => {
          console.log('p1成功啦');
          return data.data
        })

      const p2 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise2')
        .then(({
          data
        }) => {
          console.log('p2成功啦');
          return data.data
        })

      const p3 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock')
        .then(({
          data
        }) => {
          console.log('p3成功啦');
          return data.data
        })

      const p = Promise.all([p3, p1, p2])
        .then(arr => {
          console.log(arr);
          console.log('Promise.all成功啦');   
        })
        .catch(err=>{
          console.log(err,'Promise.all錯啦');
        })
    }
  </script>
</body>

</html>

我們知道axios返回的是一個promise對象,我們可以看下

 console.log(p1);


Promise.all就是用於將多個 Promise 實例,包裝成一個新的 Promise 實例
Promise.all,接收一個數組作爲參數,數組的每一項都返回Promise實例
我們重點看這段代碼

     const p = Promise.all([p3, p1, p2])
        .then(arr => {
          console.log(arr);
          console.log('Promise.all成功啦');   
        })
        .catch(err=>{
          console.log(err,'Promise.all錯啦');
        })

p1,p2,p3都是返回promise實例,Promise.all不關心他們的執行順序,如果他們都返回成功的狀態,Promise.all則返回成功的狀態,輸出一個數組,是這三個p1,p2,p3的返回值,數組的順序和他們的執行順序無關,和他們作爲參數排列的順序有關
我們看下輸出

爲了是拉長接口三的返回時間我對接口三的數據進行了修改,返回值是長度1000-2000之間的隨機數組,所以p3的執行要晚於p1和p2,
但我們輸出的arr,p3依然在前面,這給我們帶來一個便利,返回值數組的順序和方法的執行順序無關,可以進行人爲進行控制
我們將p1做一下改動,使p1報錯

 const p1 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1')
        .then(({
          data
        }) => {
          console.log('p1成功啦');
          return xxxx.data//將data.data修改爲xxxx.data
        })


如果有一個返回失敗(reject),Promise.all則返回失敗(reject)的狀態,此時第一個被reject的實例的返回值,會傳遞給P的回調函數。
三個promise實例參數之間是“與”的關係,全部成功,Promise.all就返回成功,有一個失敗,Promise.all就返回失敗
換個角度說,一個promise的執行結果依賴於另外幾個promise的執行結果,
例如:
幾個ajax全部執行完了,才能渲染頁面,
幾個ajax全部執行完了,才能做一些數據的計算操作,
不關心執行順序,只關心集體的執行結果

Promise.race()

Promise中的競態,用法和Promise.all類似,對應參數的要求和Promise.all相同,傳入一個數組作爲參數,參數要返回一個Promise實例
race就是競爭的意思,數組內的Promise實例,誰執行的快,就返回誰的執行結果,不管是成功還是失敗

const p = Promise.race([p3, p1, p2])
        .then(res => {
          console.log(res);
          console.log('Promise.all成功啦');   
        })
        .catch(err=>{
          console.log(err,'Promise.all錯啦');
        })


通過輸出我們發現
p1是第一個完成的,所以p的返回結果就是p1的執行結果
而且就算完成,但是 進程不會立即停止,還會繼續執行下去。

關於race的使用場景

搜了一下,很多文章都說是用來解決網絡超時的提示,類似於下面這樣

      const p3 = axios.get('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock')
        .then(({
          data
        }) => {
          console.log('p3成功啦');
          return data.data
        })
      const p4 = new Promise(function (resolve, reject) {
        setTimeout(() => reject(new Error('網絡連接超時')), 50)
      })
     const p = Promise.race([p3, p4])
        .then(res => console.log(res))
        .catch(err => console.log(err));

p3的ajax和50ms的定時器比較,看誰執行的快,如果超過了50ms,p3的ajax還沒返回,就告知用戶網絡連接超時
這裏有個問題,就算提示超時了,p3還在繼續執行,它並沒有停下來,直到有狀態返回
個人觀點:race可以用來爲ajax請求的時長劃定範圍,如果ajax請求時長超過xxxms會執行某個方法,或者ajax請求時長不超過xxms會執行某個方法,總之,race的應用空間不是很大

Promise.finally()

finally方法用於指定不管 Promise 對象最後狀態如何,都會執行的操作。該方法是 ES2018 引入標準的。

      const p = Promise.race([p3, p4])
        .then(res => console.log(res))
        .catch(err => console.log(err))
        .finally(() => {
          console.log("finally的執行與狀態無關")
        });

當promise得到狀態(不論成功或失敗)後就會執行finally,

原文鏈接

參考鏈接
Promise 對象
Promise.prototype.finally

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章