天天看點

也談Promise

最新的ES6标準添加有Promise方法,但自己在項目中一直使用jQuery(jQuery自己實作了不标準的Promise),加上es6标準還沒有得到普及,也就懶得學習相關資料。

最近手頭上的活少了,本着好好學習,天天向上的宗旨,便查了些資料,學習下Promise。

我們都知道js是單線程的,意味着在同一時間段,浏覽器隻能解析一段腳本。這很讓人抓狂啊。想想你自己,同一時間隻能吃零食或看電影,不能邊吃零食邊看電影,那得多崩潰啊。

許多時候,我們的業務需求需要保證這樣的資料流向:A->B->C->...>X

基于事件回調,我們可以把事件一層層嵌套,一層層回調。但這很容易導緻回調金字塔。

Promise基于這些類似的業務場景,提供給了我們解決事件回調的方案。

===============================================================

Promise

1.構造一個promise對象

1 var promise = new Promise(function(resolve, reject) {
 2             // do a thing, possibly async, then…
 3 
 4             if (/* everything turned out fine */) {
 5                 resolve("Stuff worked!");
 6             }
 7             else {
 8                 reject(Error("It broke"));
 9             }
10         });      

Promise的構造器接受一個函數作為參數,它會傳遞這個回調函數兩個變量resolve和reject。在回調函數中你可以做一些異步操作,成功之後調用resolve,否則調用reject。

2.Promise的使用

1 promise.then(function(result) {
2   console.log(result); // "Stuff worked!"
3 }, function(err) {
4   console.log(err); // Error: "It broke"
5 });      

這裡有兩個回調,第一個回調對應執行個體化Promise時reslove方法,第二個回調則對應reject方法。當然,這兩個函數都是可選的,是否使用基于個人需要。

3.Promise的鍊式調用

Promise強大的地方就在于它不僅可以配平回調金字塔,而且可以鍊式調用,每一次調用then函數,都會傳回一個Promise類。

1 var promise = new Promise(function(resolve, reject) {
 2   resolve(1);
 3 });
 4  
 5 promise.then(function(val) {
 6   console.log(val); // 1
 7   return val + 2;
 8 }).then(function(val) {
 9   console.log(val); // 3
10 });      

這裡神奇的地方就在于then函數的傳回。如果你傳回一個值,它就會被傳給下一個then回調;而如果你傳回一個Promise對象,則下一個then就會等待這個Promise明确結束(成功或失敗)才會失敗。

最佳實踐

我們有如下需求,需要首先load到資料1,資料1成功傳回後才繼續load資料2。用Promise來實作,就是下面的代碼,大家可以參考學習下

1 var getData1 = function () {
 2             return new Promise(function (resolve, reject) {
 3                 $.ajax({
 4                     dataType: "json",
 5                     url: 'testData1.json',
 6                     success: function (data) {
 7                         resolve(data);
 8                     },
 9                     error: function (err) {
10                         reject(err);
11                     }
12                 });
13             });
14         }
15         var getData2 = function () {
16             return new Promise(function (resolve, reject) {
17                 $.ajax({
18                     dataType: "json",
19                     url: 'testData2.json',
20                     success: function (data) {
21                         resolve(data);
22                     },
23                     error: function (err) {
24                         reject(err);
25                     }
26                 });
27             });
28         }
29         getData1().then(function (res) {
30             console.log('####data1');
31             console.log(res);
32             return getData2();
33         }).then(function (res) {
34             console.log('####data2');
35             console.log(res);
36         });      

我把擷取資料1和資料2分成兩個方法來實作。在getData1的then回調中,傳回getData2,這樣就能保證load到資料1再去load資料2.

=================================================================================

Promise确實強大,但可惜的是,現在能支援es6特性的浏覽器不多。很多情況下,原生的Promise不是我們的首選。

上面講到的這些特性隻是一些基本的特性,它還有許多強大的特性需要我們去挖掘。

假以時日,浏覽器端完成統一大戰,ES6得到廣泛支援,那将是前端界的一大幸事,雖然前路漫漫,但我們依舊翹首以待!

繼續閱讀