快速將 Promise 運用在開發中

sunny冰青 7年前發布 | 13K 次閱讀 Promise 前端技術

這篇文章面向對Promise不甚了解的朋友,我將告訴你如何把它快速運用在開發中。

什么是Promise?

簡單幾句介紹一下。Promise是抽象異步處理對象以及對其進行各種操作的組件。你可以理解為:它的出現,是為了讓我們更方便的進行異步處理。

在Promise出現之前,說到JavaScript的異步處理,我們都會想到回調函數,like this:

getAsync("fileA.txt", function(error, result){
  if(error){// 取得失敗時的處理 throw error;
    throw error;
  }
});

上面遵循 Node.js 的規定,回調的第一個參數是 error 。如果所有的回調函數都像 Node.js 一樣,統一參數使用規則的話,那寫法會很明了,但也僅僅是編碼規范而已,使用不同的寫法也不會出錯。

而Promise則是把異步處理對象和處理規則進行規范化,并采用統一的接口來編寫,使用規定方法之外的寫法都會出錯。

我們可以先看一個簡單的使用Promise進行異步處理的例子:

var promise = getAsyncPromise("fileA.txt");

promise.then(function(result){
  // 獲取文件內容成功時的處理
}).catch(function(error){
  // 獲取文件內容失敗時的處理
});

看上去和回調函數有些不一樣,在使用Promise進行異步處理的時候,我們必須按照接口規定的方法編寫處理代碼。

也即是說,除了使用Promise規定的方法(上面的 then 和 catch ),其他的方法都是不能使用的,而回調函數可以自定義回調的參數。

所以,Promise可以將復雜的異步處理輕松的進行模式化,沒有理由讓你不使用它。

接下來,我們看看怎么把Promise運用到開發中,這個才是大家想了解的。

學習Promise

在運用到開發之前,我們有必要先學習一些Promise的基本API(暫時看的有點糊涂沒關系,等會的例子實踐會和大家講清楚的)。

目前大致有下面三種類型:

1.Constructor(構造器)

我們從構造函數 Promise 來創建一個新 promise 對象作為接口。

要創建一個 promise 對象,可以使用 new 來調用 Promise 構造器來進行實例化。

var promise = new Promise(function(resolve, reject) { // 異步處理
  // 處理結束后、調用resolve 或 reject
});

2.Instance Method(實例方法)

在通過 new 生成的 promise 對象時,我們設置了在resolve(成功)和reject(失敗)時調用的回調函數,我們可以使用 promise.then() 實例方法。

promise.then(onFulfilled,onReject);
  • resolve(成功)時: onFulfilled 會被調用

  • reject(失敗)時: onReject 會被調用

onFulfilled 和 onReject 都為可選參數

promise.then 成功和失敗時都可以使用,另外在異常處理時,可以使用 promise.then(undefined, onReject) 這種方式,只指定 reject 時的回調函數即可。不過這種情況下,使用 promise.catch() 是個明智之選。

promise.catch(onReject);

3.Static Method(靜態方法)

像 promise.all() 和 Promise.resolve() 等在內,主要都是一些輔助方法(可以理解為一些語法糖),這里不作深入探討。

運用在開發中

我們先來看一段Promise使用流程代碼:

function asyncFunction() {  //(1)
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('Async Hello World');
    }, 300);
  });
}

asyncFunction().then(function(value) {  //(2)
  console.log(value); //300ms后打印 "Async Hello World"
}).catch(function(error) {  //(3)
  console.log(error);
})

分析一下上面代碼。

執行 (1) 處函數,會返回一個Promise對象,Promise對象內部在300ms后執行 resolve() 方法,這個方法調用 (2) 處的 then() 方法,并傳入參數,如果Promise對象內部出現任何錯誤(比如平臺不支持setTimeout方法),就會執行 (3) 處的 catch() 發放,并把錯誤作為參數傳入。

這里提一下,我看到很多朋友把Promise理解為Ajax的一種擴展,其實并不是這樣的,Ajax只是一種請求數據的方式,因為Ajax是異步的,所以我們可以用Promise去管理Ajax請求,但這并不意味這Promise只服務于Ajax,只要是異步處理,我們都可以使用Promise去處理,就比如上面的 setTimeout 。

看到這里大家對Promise應該有一個大概的認識了,實際開發中Promise大部分時間還是搭配Ajax使用,我們來看看應該怎么做,下面用原生的方式請求Ajax,大家也溫習一下:

function getURL(URL) {
  return new Promise(function(resolve, reject) {
    var req = new XMLHttpRequest();

    req.open('GET', URL, true);

    req.onload = function() {
      if (req.status === 200) {
        resolve(req.responseText);
      }else {
        reject(new Error(req.statusText));
      }
    };

    req.onerror = function() {
      reject.(new Error(req.statusText));
    };

    req.send();
  });
}

// 運行示例
var URL = "https://rockjins.js.org";
getURL(URL).then(function onFulfilled(value){
  console.log(value);
}).catch(function onRejected(error){
  console.error(error);
});

getURL 只有在XHR取得狀態為200時才會調用 resolve ,也就是數據取得成功時,而其他情況(數據取得失敗)則會調用 reject 。

當調用 resolve(req.responseText) 時, then 方法也會被調用,并接收到 req.responseText 參數。

熟悉Node.js的朋友在寫回調時會會將 callback(error,response) 的第一個參數設為 error 對象,在Promise中,resolve(成功)/reject(失敗)擔當了這個職責。

XHR中 onerror 觸發時,就是發生錯誤時,理所當然要調用 reject ,我們重點來看下傳給 reject 的值。

發生錯誤時要像這樣 reject(new Error(req.statusText)) ,創建一個Error對象再講具體的值傳入進去。傳給 reject 的值也沒有什么特殊限制,一般只要是Error對象(或繼承自Error對象)即可。

小結

其實你理解了Promise的運作流程,使用它十分方便和簡單,它就是一個異步管理器,幫助我們更好地去進行異步處理。

試想,如果Promise真的很復雜,那它出現的意義是什么?本末倒置了,哈哈。

 

 

來自:https://juejin.im/post/58c5a621570c35006d66eee9

 

 本文由用戶 sunny冰青 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!