這篇文章面向對Promise不甚瞭解的朋友,我將告訴你如何把它快速運用在開發中。javascript
簡單幾句介紹一下。Promise是抽象異步處理對象以及對其進行各類操做的組件。你能夠理解爲:它的出現,是爲了讓咱們更方便的進行異步處理。java
在Promise出現以前,說到JavaScript的異步處理,咱們都會想到回調函數,like this:promise
getAsync("fileA.txt", function(error, result){
if(error){// 取得失敗時的處理 throw error;
throw error;
}
});複製代碼
上面遵循Node.js
的規定,回調的第一個參數是error
。若是全部的回調函數都像Node.js
同樣,統一參數使用規則的話,那寫法會很明瞭,但也僅僅是編碼規範而已,使用不一樣的寫法也不會出錯。微信
而Promise則是把異步處理對象和處理規則進行規範化,並採用統一的接口來編寫,使用規定方法以外的寫法都會出錯。異步
咱們能夠先看一個簡單的使用Promise進行異步處理的例子:async
var promise = getAsyncPromise("fileA.txt");
promise.then(function(result){
// 獲取文件內容成功時的處理
}).catch(function(error){
// 獲取文件內容失敗時的處理
});複製代碼
看上去和回調函數有些不同,在使用Promise進行異步處理的時候,咱們必須按照接口規定的方法編寫處理代碼。函數
也便是說,除了使用Promise規定的方法(上面的then
和catch
),其餘的方法都是不能使用的,而回調函數能夠自定義回調的參數。學習
因此,Promise能夠將複雜的異步處理輕鬆的進行模式化,沒有理由讓你不使用它。ui
接下來,咱們看看怎麼把Promise運用到開發中,這個纔是你們想了解的。this
在運用到開發以前,咱們有必要先學習一些Promise的基本API(暫時看的有點糊塗不要緊,等會的例子實踐會和你們講清楚的)。
目前大體有下面三種類型:
咱們從構造函數Promise
來建立一個新promise
對象做爲接口。
要建立一個promise
對象,可使用new
來調用Promise
構造器來進行實例化。
var promise = new Promise(function(resolve, reject) { // 異步處理
// 處理結束後、調用resolve 或 reject
});複製代碼
在經過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);複製代碼
像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真的很複雜,那它出現的意義是什麼?本末倒置了,哈哈。
喜歡本文的朋友能夠關注個人微信公衆號,不按期推送一些好文。
本文出自Rockjins Blog,轉載請與做者聯繫。不然將追究法律責任。