1. 程式人生 > 其它 >P14.3-Promise終極鏈式呼叫寫法

P14.3-Promise終極鏈式呼叫寫法

技術標籤:最美前端# VUE【構建vue專案】

P14.3-Promise終極鏈式呼叫寫法

文章目錄

1.概述

使用Promise封裝多層非同步呼叫時,呼叫層級越多,重複程式碼就越多,這個時候我們可將重複的程式碼去掉,簡化封裝非同步請求的程式碼。這種簡化寫法就是Promise鏈式呼叫

2.Promise鏈式呼叫思想

我們在看Promise的流程圖時,發現無論是then還是catch都可以返回一個Promise物件。
所以,我們的程式碼其實是可以進行鏈式呼叫的:

  • 這裡我們直接通過Promise包裝了一下新的資料,將Promise物件返回了
  • Promise.resovle():將資料包裝成Promise物件,並且在內部回撥resolve()函式
  • Promise.reject():將資料包裝成Promise物件,並且在內部回撥reject()函式

3.Promise鏈式呼叫標準寫法

這種鏈式寫法是一個標準的寫法,每次請求都會建立一個Promise物件在物件中傳送下次非同步請求。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>


<script>


  // 引數 -> 函式(resolve, reject)
  // resolve, reject本身它們又是函式
  // 鏈式程式設計
  new Promise((resolve, reject) => {

    // 第一次網路請求的程式碼
setTimeout(() => { resolve() }, 1000) }).then(() => { // 第一次拿到結果的處理程式碼 console.log('Hello World'); console.log('Hello World'); console.log('Hello World'); console.log('Hello World'); console.log('Hello World'); console.log('Hello World'); return new Promise((resolve, reject) => { // 第二次網路請求的程式碼 setTimeout(() => { resolve() }, 1000) }) }).then(() => { // 第二次處理的程式碼 console.log('Hello Vuejs'); console.log('Hello Vuejs'); console.log('Hello Vuejs'); console.log('Hello Vuejs'); console.log('Hello Vuejs'); console.log('Hello Vuejs'); return new Promise((resolve, reject) => { // 第三次網路請求的程式碼 setTimeout(() => { resolve() }) }) }).then(() => { // 第三處理的程式碼 console.log('Hello Python'); console.log('Hello Python'); console.log('Hello Python'); console.log('Hello Python'); console.log('Hello Python'); })
</script> </body> </html>

4.Promise鏈式呼叫第一種簡化寫法

需求場景描述
第一次非同步請求返回結果,在第一請求中進行處理。然後將處理結果傳遞給第二次請求
第二次請求拿到第一次非同步請求處理的結果進行處理後傳送第二次請求
第三次請求拿到第二次請求處理的結果進行處理然後傳送第三次請求
注意在這個場景中只有第一次是非同步請求,後面不是非同步請求。只是拿到上次結果做處理然後傳送請求。

4.1.Promise鏈式呼叫標準寫法

首先使用標準鏈式呼叫方法實現上面的場景需求。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<script>
 
  /* 需求描述
  網路請求: aaa -> 自己處理(10行)
  處理: aaa111 -> 自己處理(10行)
  處理: aaa111222 -> 自己處理 */
  
  new Promise((resolve, reject) => {
  //只有第一次請求使用了setTime非同步請求
    setTimeout(() => {
      resolve('aaa')
    }, 1000)
  }).then(res => {
    // 1.自己處理10行程式碼
    console.log(res, '第一層的10行處理程式碼');
  
    // 2.對結果進行第一次處理
    return new Promise((resolve, reject) => {
      // resolve(res + '111')
      reject('err')
    })
  }).then(res => {
    console.log(res, '第二層的10行處理程式碼');
  
    return new Promise(resolve => {
      resolve(res + '222')
    })
  }).then(res => {
    console.log(res, '第三層的10行處理程式碼');
  }).catch(err => {
    console.log(err);
  })
</script>
</body>
</html>

4.2.Promise鏈式呼叫第一次簡化寫法

上面的程式碼只有第一次使用了非同步請求,後面的請求都是呼叫上次resolve函式返回的結果,所以我們可以去掉後面建立Promise物件。每次都返回Promise物件呼叫resolve返回的結果,如果是呼叫reject,同理只需將resolve替換成reject即可。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<script>
 // new Promise(resolve => resolve(結果))簡寫
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('aaa')
    }, 1000)
  }).then(res => {
    // 1.自己處理10行程式碼
    console.log(res, '第一層的10行處理程式碼');

    // 2.對結果進行第一次處理
    return Promise.resolve(res + '111')
  }).then(res => {
    console.log(res, '第二層的10行處理程式碼');

    return Promise.resolve(res + '222')
  }).then(res => {
    console.log(res, '第三層的10行處理程式碼');
  })
</script>
</body>
</html> 

4.3.Promise鏈式呼叫第終極簡化寫法

上面程式碼中每次處理請求返回的結果(return Promise.resolve(res + ‘111’))都要手動通過Promise.resolve呼叫resole函式 ,這個也是重複的程式碼,我們也可以省去,程式碼內部會自動進行包裝處理。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<script>
// 省略掉Promise.resolve
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('aaa')
    }, 1000)
  }).then(res => {
    // 1.自己處理10行程式碼
    console.log(res, '第一層的10行處理程式碼');

    // 2.對結果進行第一次處理
    return res + '111'
  }).then(res => {
    console.log(res, '第二層的10行處理程式碼');

    return res + '222'
  }).then(res => {
    console.log(res, '第三層的10行處理程式碼');
  })
</script>
</body>
</html>

4.4.Promise鏈式呼叫包含請求失敗寫法

上面所有的鏈式呼叫都是建立在假設所有請求都是成功情況下的寫法,在真實請求中會出現請求失敗情況,這裡我們就加上請求失敗來寫鏈式呼叫。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<script>
new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('aaa')
    }, 1000)
  }).then(res => {
    // 1.自己處理10行程式碼
    console.log(res, '第一層的10行處理程式碼');

    // 2.對結果進行第一次處理,執行到這裡假如請求失敗了呼叫reject函式。後面的請求都不在執行直接呼叫最後一行的catch函式處理請求失敗程式碼。
    return Promise.reject('error message')
  }).then(res => {
    console.log(res, '第二層的10行處理程式碼');

    return Promise.resolve(res + '222')
  }).then(res => {
    console.log(res, '第三層的10行處理程式碼');
  }).catch(err => {
    console.log(err);
  })
</script>
</body>
</html>

在這裡插入圖片描述