[轉]JS - Promise使用詳解2(ES6中的Promise)

原文地址:https://www.hangge.com/blog/cache/detail_1638.htmlhtml

2015年6月, ES2015(即 ECMAScript 六、ES6) 正式發佈。其中 Promise 被列爲正式規範,成爲 ES6 中最重要的特性之一。數組

 

1,then()方法

簡單來說,then 方法就是把原來的回調寫法分離出來,在異步操做執行完後,用鏈式調用的方式執行回調函數。
而 Promise 的優點就在於這個鏈式調用。咱們能夠在 then 方法中繼續寫 Promise 對象並返回,而後繼續調用 then 來進行回調操做。
 
(1)下面經過樣例做爲演示,咱們定義作飯、吃飯、洗碗(cook、eat、wash)這三個方法,它們是層層依賴的關係,下一步的的操做須要使用上一部操做的結果。(這裏使用 setTimeout 模擬異步操做)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//作飯
function  cook(){
     console.log( '開始作飯。' );
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '作飯完畢!' );
             resolve( '雞蛋炒飯' );
         }, 1000);
     });
     return  p;
}
 
//吃飯
function  eat(data){
     console.log( '開始吃飯:'  + data);
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '吃飯完畢!' );
             resolve( '一塊碗和一雙筷子' );
         }, 2000);
     });
     return  p;
}
 
function  wash(data){
     console.log( '開始洗碗:'  + data);
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '洗碗完畢!' );
             resolve( '乾淨的碗筷' );
         }, 2000);
     });
     return  p;
}


(2)使用 then 鏈式調用這三個方法:promise

1
2
3
4
5
6
7
8
9
10
cook()
.then( function (data){
     return  eat(data);
})
.then( function (data){
     return  wash(data);
})
.then( function (data){
     console.log(data);
});


固然上面代碼還能夠簡化成以下:異步

1
2
3
4
5
6
cook()
.then(eat)
.then(wash)
.then( function (data){
     console.log(data);
});


(3)運行結果以下:函數

原文:JS - Promise使用詳解2(ES6中的Promise)

2,reject()方法

上面樣例咱們經過 resolve 方法把 Promise 的狀態置爲完成態(Resolved),這時 then 方法就能捕捉到變化,並執行「成功」狀況的回調。
而 reject 方法就是把 Promise 的狀態置爲已失敗(Rejected),這時 then 方法執行「失敗」狀況的回調(then 方法的第二參數)。
 
(1)下面一樣使用一個樣例作演示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//作飯
function  cook(){
     console.log( '開始作飯。' );
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '作飯失敗!' );
             reject( '燒焦的米飯' );
         }, 1000);
     });
     return  p;
}
 
//吃飯
function  eat(data){
     console.log( '開始吃飯:'  + data);
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '吃飯完畢!' );
             resolve( '一塊碗和一雙筷子' );
         }, 2000);
     });
     return  p;
}
 
cook()
.then(eat,  function (data){
   console.log(data +  '無法吃!' );
})

運行結果以下:spa

原文:JS - Promise使用詳解2(ES6中的Promise)
(2)若是咱們只要處理失敗的狀況可使用 then(null, ...),或是使用接下來要講的 catch 方法。
1
2
3
4
cook()
.then( null function (data){
   console.log(data +  '無法吃!' );
})

 

3,catch()方法

(1)它能夠和 then 的第二個參數同樣,用來指定 reject 的回調rest

1
2
3
4
5
cook()
.then(eat)
. catch ( function (data){
     console.log(data +  '無法吃!' );
});


(2)它的另外一個做用是,當執行 resolve 的回調(也就是上面 then 中的第一個參數)時,若是拋出異常了(代碼出錯了),那麼也不會報錯卡死 js,而是會進到這個 catch 方法中。code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//作飯
function  cook(){
     console.log( '開始作飯。' );
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '作飯完畢!' );
             resolve( '雞蛋炒飯' );
         }, 1000);
     });
     return  p;
}
 
//吃飯
function  eat(data){
     console.log( '開始吃飯:'  + data);
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '吃飯完畢!' );
             resolve( '一塊碗和一雙筷子' );
         }, 2000);
     });
     return  p;
}
 
cook()
.then( function (data){
     throw  new  Error( '米飯被打翻了!' );
     eat(data);
})
. catch ( function (data){
     console.log(data);
});

運行結果以下:htm

原文:JS - Promise使用詳解2(ES6中的Promise)
這種錯誤的捕獲是很是有用的,由於它可以幫助咱們在開發中識別代碼錯誤。好比,在一個 then() 方法內部的任意地方,咱們作了一個 JSON.parse() 操做,若是 JSON 參數不合法那麼它就會拋出一個同步錯誤。用回調的話該錯誤就會被吞噬掉,可是用 promises 咱們能夠輕鬆的在 catch() 方法裏處理掉該錯誤。
 
(3)還能夠添加多個 catch,實現更加精準的異常捕獲。
1
2
3
4
5
6
7
8
9
10
11
somePromise.then( function () {
  return  a();
}). catch (TypeError,  function (e) {
  //If a is defined, will end up here because
  //it is a type error to reference property of undefined
}). catch (ReferenceError,  function (e) {
  //Will end up here if a wasn't defined at all
}). catch ( function (e) {
  //Generic catch-the rest, error wasn't TypeError nor
  //ReferenceError
});
 

4,all()方法

Promise 的 all 方法提供了並行執行異步操做的能力,而且在全部異步操做執行完後才執行回調。
 
(1)好比下面代碼,兩個個異步操做是並行執行的,等到它們都執行完後纔會進到 then 裏面。同時 all 會把全部異步操做的結果放進一個數組中傳給 then。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//切菜
function  cutUp(){
     console.log( '開始切菜。' );
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '切菜完畢!' );
             resolve( '切好的菜' );
         }, 1000);
     });
     return  p;
}
 
//燒水
function  boil(){
     console.log( '開始燒水。' );
     var  p =  new  Promise( function (resolve, reject){         //作一些異步操做
         setTimeout( function (){
             console.log( '燒水完畢!' );
             resolve( '燒好的水' );
         }, 1000);
     });
     return  p;
}
 
Promise
.all([cutUp(), boil()])
.then( function (results){
     console.log( "準備工做完畢:" );
     console.log(results);
});


(2)運行結果以下:對象

原文:JS - Promise使用詳解2(ES6中的Promise)

5,race()方法

race 按字面解釋,就是賽跑的意思。race 的用法與 all 同樣,只不過 all 是等全部異步操做都執行完畢後才執行 then 回調。而 race 的話只要有一個異步操做執行完畢,就馬上執行 then 回調。
注意:其它沒有執行完畢的異步操做仍然會繼續執行,而不是中止。
 
(1)這裏咱們將上面樣例的 all 改爲 race
1
2
3
4
5
6
Promise
.race([cutUp(), boil()])
.then( function (results){
     console.log( "準備工做完畢:" );
     console.log(results);
});
原文:JS - Promise使用詳解2(ES6中的Promise)
 
(2)race 使用場景不少。好比咱們能夠用 race 給某個異步請求設置超時時間,而且在超時後執行相應的操做。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//請求某個圖片資源
function  requestImg(){
     var  p =  new  Promise( function (resolve, reject){
     var  img =  new  Image();
     img.onload =  function (){
        resolve(img);
     }
     img.src =  'xxxxxx' ;
     });
     return  p;
}
 
//延時函數,用於給請求計時
function  timeout(){
     var  p =  new  Promise( function (resolve, reject){
         setTimeout( function (){
             reject( '圖片請求超時' );
         }, 5000);
     });
     return  p;
}
 
Promise
.race([requestImg(), timeout()])
.then( function (results){
     console.log(results);
})
. catch ( function (reason){
     console.log(reason);
});

上面代碼 requestImg 函數異步請求一張圖片,timeout 函數是一個延時 5 秒的異步操做。咱們將它們一塊兒放在 race 中賽跑。

  • 若是 5 秒內圖片請求成功那麼便進入 then 方法,執行正常的流程。
  • 若是 5 秒鐘圖片還未成功返回,那麼則進入 catch,報「圖片請求超時」的信息。
原文:JS - Promise使用詳解2(ES6中的Promise)
相關文章
相關標籤/搜索