快來使用ES2015的Promise吧

2018-06-17 10:58 更新

接觸Promise很久了,但一直也沒用過,感覺很陌生,但是ES2015來了,是時候使用了,本文將介紹Promise的方方面面,同時也是自己學習的過程。

閱讀須知

本文將會盡可能使用ES2015的語法,這可能需要你使用一款現(xiàn)代瀏覽器,如果你還不了解可以閱讀下這篇文章。

兼容性

Promise的瀏覽器兼容性如下,你需要選一款兼容的瀏覽器才可以,你也可以點擊這里查看。

什么是Promise

Promise其實是Node社區(qū)中誕生的產物,如果你寫過Node你肯定會知道為了異步,寫了那么多的回調,而Promise就是比回調更有好的方式。

所謂Promise,就是一個對象,用來傳遞異步操作的消息。它代表了某個未來才會知道結果的事件(通常是一個異步操作),并且這個事件提供統(tǒng)一的API,可供進一步處理。

如果你有興趣可以閱讀一下Promise的規(guī)范,但我不太感興趣,我將從實踐的角度來學習它。

new Promise

Promise是一個構造函數(shù)(類),可以使用new運算符新建一個實例,然后就可以使用了,構造函數(shù)接受一個函數(shù)作為參數(shù)。

var p = new Promise((resolve, reject) => {
    window.setTimeout(() => {resolve(123);}, 1000);
});

p.then((data) => {
    console.log('p success', data);
});

上面的代碼輸出如下:

=> p success 123

新建Promise對象時傳入的函數(shù),接受兩個參數(shù),resolve和reject,分別用來改變Promise的狀態(tài),創(chuàng)建好,調用resolve和reject時,可以傳入?yún)?shù),這個參數(shù)會自動傳遞個后面的回調函數(shù)中。

創(chuàng)建好promise后,可以通過then方法定制狀態(tài)變化后的回調函數(shù)。

好了這就是使用Promise的全部代碼了,剩下的部分就全靠你的發(fā)揮了,下面將會介紹常用的API。

Promise.prototype 屬性

打開瀏覽器的控制臺,輸入如下代碼:

Object.getOwnPropertyNames(Promise.prototype).sort().forEach(function (val) {console.log(val, '\n')});

在我的瀏覽器中上面的代碼會有如下輸出,可能不同瀏覽器會不一樣。

這里我們將重點關注如下接口:

  • catch
  • then

Promise.prototype.catch

catch() 方法只處理Promise被拒絕的情況,并返回一個Promise。該方法的行為和調用Promise.prototype.then(undefined, onRejected)相同。

p.catch((reason) => {
   // 拒絕
});

更多信息,請點擊這里查看。

Promise.prototype.then

then()方法返回一個Promise。它有兩個參數(shù),分別為Promise在 success 和 failure 情況下的回調函數(shù)。

p.then((value) => {
   // 滿足
  }, (reason) => {
  // 拒絕
});

更多信息,請點擊這里查看。

Promise 屬性

我們也先來看看瀏覽器支持哪些接口,在控制臺輸入如下代碼:

Object.getOwnPropertyNames(Promise).sort().forEach(function (val) {console.log(val, '\n')});

會看到如下的輸出:

我們將重點關注一下屬性:

  • all
  • race
  • reject
  • resolve

Promise.all

Promise.all(iterable) 方法返回一個promise,該promise會在iterable參數(shù)內的所有promise都被解決后被解決。

Promise.all(iterable);

iterable是一個可迭代對象,比如Array。

更多信息,請點擊這里查看。

Promise.race

Promise.race(iterable)方法返回一個promise,這個promise在iterable中的任意一個promise被解決或拒絕后,立刻以相同的解決值被解決或以相同的拒絕原因被拒絕。

Promise.race(iterable);

iterable是一個可迭代對象,比如Array。

更多信息,請點擊這里查看。

Promise.reject

Promise.reject(reason)方法返回一個用reason拒絕的Promise。

Promise.reject(reason);

reason Promise被拒絕的原因。

更多信息,請點擊這里查看。

Promise.resolve

Promise.resolve(value)方法返回一個以給定值resolve掉的Promise對象。但如果這個值是thenable的(就是說帶有then方法),返回的promise會“追隨”這個thenable的對象,接收它的最終狀態(tài)(指resolved/rejected/pendding/settled);否則這個被返回的promise對象會以這個值被fulfilled。

Promise.resolve(value);
Promise.resolve(promise);
Promise.resolve(thenable);

value 用來resolve待返回的promise對象的參數(shù)。既可以是一個Promise對象也可以是一個thenable。

更多信息,請點擊這里查看。

實戰(zhàn)

我們構造一段下面的代碼,基本上用到了上面的全部知識:

// 1000ms 后success
var p1 = new Promise((resolve, reject) => {
    window.setTimeout(() => {resolve(123);}, 1000);
});

p1.then((data) => {
    console.log('p1 success', data);
});

// 2000ms 后success
var p2 = new Promise((resolve, reject) => {
    window.setTimeout(() => {resolve(456);}, 2000);
}); 

p2.then((data) => {
    console.log('p2 success', data);
});

var pa = Promise.all([p1, p2]);
var pr = Promise.race([p1, p2]);

pa.then((data) => {
    console.log('pa success', data);
});

pr.then((data) => {
    console.log('pr success', data);
});

上面的代碼輸出如下:

// 1000ms
p1 success 123
pr success 123

// 2000ms
p2 success 456
pa success [123, 456]

Polyfill

如果要兼容舊的瀏覽器,又要使用新特性,那么只能使用Polyfill了,類似的庫很多,我推薦使用es6-promise

es6-promise是一個兼容 ES6 Promises 的Polyfill類庫。 它基于 RSVP.js 這個兼容 Promises/A+ 的類庫, 它只是 RSVP.js 的一個子集,只實現(xiàn)了Promises 規(guī)定的 API。

關于使用方法和注意事項這個庫的文檔都寫得很詳細了,在此不再詳細介紹了。

總結

是時候使用Promise了,上面已經介紹了ES2015 Promise的全部內容了,如果你還想閱讀更多資料,可查看下面的參考資料,如果你有任何疑問或建議,歡迎在下面的評論區(qū)和我討論。

參考資料

原文網址:http://yanhaijing.com/javascript/2015/09/16/es6-promise/

歡迎訂閱我的微信公眾帳號,只推送原創(chuàng)文字。掃碼或搜索:顏海鏡

打賞其他方式

本文對你有幫助?那就賞杯咖啡吧

微信掃一掃轉賬 支付寶掃一掃轉賬
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號