1. 程式人生 > >30天入坑React ---------------day15 Promises

30天入坑React ---------------day15 Promises

這篇文章是系列的一部分 。

在本系列中,我們將從非常基礎開始,逐步瞭解您需要了解的所有內容,以便開始使用React。如果您曾經想學習React,那麼這裡就是您的最佳選擇!

30天的React Mini-Ebook

promise(承諾)簡介

今天,我們將看一下從高層次瞭解Promise需要了解的內容,因此我們可以使用這個非常有用的概念構建我們的應用程式。

昨天我們將fetch庫安裝到我們create-react-app第12天開始的專案中。今天我們就從昨天拿起討論的概念和技術承諾

什麼是promise(承諾)

正如Mozilla所定義的,一個Promise物件用於處理非同步計算,這些計算具有一些重要的保證,這些保證很難用回撥方法處理(處理非同步程式碼的老派方法)。

一個Promise目的是簡單地圍繞可或可不當物件被例項化,並提供用於處理的值的方法是已知的一個值的包裝它是已知的(也稱為resolved)或為失敗原因不可用的(我們將參照對此as rejected)。

使用Promise物件使我們有機會將非同步操作的功能與最終的成功或失敗相關聯(無論出於何種原因)。它還允許我們通過使用類似同步的程式碼來處理這些複雜的場景。

例如,考慮以下同步程式碼,我們在JavaScript控制檯中打印出當前時間:

var currentTime = new Date();
console.log('The current time is: ' + currentTime);

這非常簡單,因為new Date()物件代表瀏覽器知道的時間。現在考慮我們在其他遠端機器上使用不同的時鐘。例如,如果我們正在製作新年快樂時鐘,那麼能夠將使用者的瀏覽器與所有人同步使用單個時間值對所有人進行同步非常棒,因此沒有人錯過了落球儀式。

假設我們有一個方法來處理獲取當前時間的方法,該時鐘getCurrentTime()從遠端伺服器獲取當前時間。我們現在用一個setTimeout()返回時間來表示這個(就像它向一個緩慢的API發出請求):

function getCurrentTime() {
  // Get the current 'global' time from an API
  return setTimeout(function() {
    return new Date();
  }, 2000);
}
var currentTime = getCurrentTime()
console.log('The current time is: ' + currentTime);

我們的console.log()日誌值將返回超時處理程式ID,這絕對不是當前時間。傳統上,我們可以使用回撥更新程式碼,以便在時間可用時呼叫:

function getCurrentTime(callback) {
  // Get the current 'global' time from an API
  return setTimeout(function() {
    var currentTime = new Date();
    callback(currentTime);
  }, 2000);
}
getCurrentTime(function(currentTime) {
  console.log('The current time is: ' + currentTime);
});

如果其餘的有錯誤怎麼辦?我們如何捕獲錯誤並定義重試或錯誤狀態?

function getCurrentTime(onSuccess, onFail) {
  // Get the current 'global' time from an API
  return setTimeout(function() {
    // randomly decide if the date is retrieved or not
    var didSucceed = Math.random() >= 0.5;
    if (didSucceed) {
      var currentTime = new Date();
      onSuccess(currentTime);
    } else {
      onFail('Unknown error');
    }
  }, 2000);
}
getCurrentTime(function(currentTime) {
  console.log('The current time is: ' + currentTime);
}, function(error) {
  console.log('There was an error fetching the time');
});

現在,如果我們想根據第一個請求的值發出請求怎麼辦?作為一個簡短的例子,讓我們重新使用getCurrentTime()裡面的函式(好像它是第二種方法,但允許我們避免新增另一個複雜的函式):

function getCurrentTime(onSuccess, onFail) {
  // Get the current 'global' time from an API
  return setTimeout(function() {
    // randomly decide if the date is retrieved or not
    var didSucceed = Math.random() >= 0.5;
    console.log(didSucceed);
    if (didSucceed) {
      var currentTime = new Date();
      onSuccess(currentTime);
    } else {
      onFail('Unknown error');
    }
  }, 2000);
}
getCurrentTime(function(currentTime) {
  getCurrentTime(function(newCurrentTime) {
    console.log('The real current time is: ' + currentTime);
  }, function(nestedError) {
    console.log('There was an error fetching the second time');
  })
}, function(error) {
  console.log('There was an error fetching the time');
});

以這種方式處理非同步可能會很快變得複雜。另外,我們可以從前一個函式呼叫中獲取值,如果我們只想獲得一個...當處理我們的應用程式啟動時尚未提供的值時,有很多棘手的情況需要處理。

輸入promise​​​​​​​(承諾)

另一方面,使用promises可以幫助我們避免很多這種複雜性(儘管不是銀彈解決方案)。以前的程式碼,可以稱為義大利麵條程式碼,可以變成更整潔,更同步的版本:

function getCurrentTime(onSuccess, onFail) {
  // Get the current 'global' time from an API using Promise
  return new Promise((resolve, reject) => {
    setTimeout(function() {
      var didSucceed = Math.random() >= 0.5;
      didSucceed ? resolve(new Date()) : reject('Error');
    }, 2000);
  })
}
getCurrentTime()
  .then(currentTime => getCurrentTime())
  .then(currentTime => {
    console.log('The current time is: ' + currentTime);
    return true;
  })
  .catch(err => console.log('There was an error:' + err))

這個先前的原始碼示例對於發生了什麼有點清晰和明確,並避免了許多棘手的錯誤處理/捕獲。

為了抓住成功的價值,我們將使用例項物件then()上的可用功能Promisethen()無論promise本身的返回值是什麼,都會呼叫該函式。例如,在上面的示例中,getCurrentTime()函式使用currentTime()值(成功完成時)解析並then()在返回值(這是另一個promise)上呼叫函式,依此類推。

為了捕獲promise鏈中任何地方發生的錯誤,我們可以使用該catch()方法。

我們在上面的例子中使用了一個promise鏈來建立一個接一個地呼叫的動作。承諾鏈聽起來很複雜,但它基本上很簡單。從本質上講,我們可以連續“同步”多個非同步操作的呼叫。then()使用前一個then()函式的返回值呼叫每個呼叫。

例如,如果我們想要操縱getCurrentTime()呼叫的值,我們可以在鏈中新增一個連結,如下所示:

getCurrentTime()
  .then(currentTime => getCurrentTime())
  .then(currentTime => {
    return 'It is now: ' + currentTime;
  })
  // this logs: "It is now: [current time]"
  .then(currentTimeMessage => console.log(currentTimeMessage))
  .catch(err => console.log('There was an error:' + err))

一次性使用保證

promise​​​​​​​(承諾)在任何給定時間都只有三種狀態之一:

  • 有待
  • 履行(已解決)
  • 拒絕(錯誤)

一個懸而未決的承諾永遠只能導致無論是完成狀態或拒絕狀態一次且僅一次,可避免一些非常複雜的錯誤情況。這意味著我們只能回覆一次承諾。如果我們想重新執行使用promises的函式,我們需要建立一個函式。

創造一個promise​​​​​​​(承諾)

我們可以使用Promise建構函式建立新的promise(如上所示)。它接受一個將使用兩個引數執行的函式:

  • 成功解析時要呼叫的onSuccess(或resolve)函式
  • 在失敗拒絕時呼叫的onFail(或reject)函式

從上面回顧我們的函式,我們可以看到,resolve()如果請求成功,我們呼叫reject()函式,如果方法返回錯誤條件,則呼叫函式。

var promise = new Promise(function(resolve, reject) {
  // call resolve if the method succeeds
  resolve(true);
})
promise.then(bool => console.log('Bool is true'))

既然我們知道promise​​​​​​​(承諾)是什麼,如何使用,以及如何建立它們,我們實際上可以開始使用fetch()我們昨天安裝的庫。DD

學習REACT正確的方法

React和朋友的最新,深入,完整的指南。

下載第一章

❮上一個

下一章:

顯示遠端資料

下一個 ❯

本教程系列的完整原始碼可以在GitHub repo找到,其中包括所有樣式和程式碼示例。

如果您在任何時候感到困難,還有其他問題,請隨時通過以下方式與我們聯絡: