1. 程式人生 > >ES6中的Promise使用總結

ES6中的Promise使用總結

One、什麼是Promise?

Promise是非同步程式設計的解決方案,而它本身也就是一個建構函式,比傳統的非同步解決【回撥函式】和【事件】更合理,更強大。

Two、Promise有何作用?

作用:解決回撥地獄

當我們在寫邏輯函式時,可能函式內部會有另一個函式,而我們在處理一些比較複雜的操作的時候,有可能裡面會巢狀十幾二十個函式都說不定,那麼看一下下面的程式碼: 

 1 //需求 : 非同步操作按照順序執行(非同步預設無序)
 2 
 3 //需求: (1)先讀取a  (2)然後讀取b (3)然後讀c  (4)最後讀取d
 4 
 5 
 6 const fs = require('fs');
 7 
 8 //下面出現了回撥地獄
 9 //(1)讀取A
10 fs.readFile('./data/a.txt', 'utf8', (err, data) => {
11     if (err) {
12         throw err;
13     } else {
14         console.log(data);
15         //(2)讀取B
16         fs.readFile('./data/b.txt', 'utf8', (err, data) => {
17             if (err) {
18                 throw err;
19             } else {
20                 console.log(data);
21                 //(3)讀取C
22                 fs.readFile('./data/c.txt', 'utf8', (err, data) => {
23                     if (err) {
24                         throw err;
25                     } else {
26                         console.log(data);
27                         //(4)讀取D
28                         fs.readFile('./data/d.txt', 'utf8', (err, data) => {
29                             if (err) {
30                                 throw err;
31                             } else {
32                                 console.log(data);
33                             }
34                         })
35                     }
36                 })
37             }
38         })
39     }
40 })
View Code

像這樣的程式碼維護起來非常麻煩,那麼如何使用Promise來解決?看下來:

Three、promise基本使用:

 

(1)例項化promise物件(將非同步放入promise容器) :

let p = new Promise((resolve,reject)=>{ 你的非同步操作 })

(2)呼叫promise例項的then方法 (處理非同步結果): 

p.then(data=>{},err=>{})

再看一個根據上面優化的程式碼:

 

 

 1 const fs = require('fs');
 2 
 3 //1.建立Promise例項化物件  (Promise是一個建構函式,作用是建立promise例項)
 4 //引數是一個回撥函式 :  (resolve, reject)=>{ 你的非同步操作 }
 5 let p = new Promise((resolve,reject)=>{
 6     fs.readFile('./data/b.txt','utf8',(err,data)=>{
 7         if(!err){
 8             //成功
 9             /* 
10             1.成功就執行resolve() , 會呼叫then的第一個函式
11             */
12             resolve(data);
13         }else{
14             //失敗
15             /* 
16             2.失敗就執行reject(),會呼叫then的第二個函式
17             */
18             reject(err);
19         }
20     });
21 });
22 
23 
24 //2.呼叫promise例項的then方法
25 /* 
26 第一個引數:  回撥函式  (data)=>{}
27 第二個引數:  回撥函式  (err)=>{}
28 */
29 p.then(data=>{
30     //成功
31     console.log(data);
32     
33 },err=>{
34     //失敗
35     console.log(err);
36     
37 });
View Code

 

Four、Promise原理介紹 :

 

(1)promise有三種狀態
         pending:進行中
    fulfilled:已成功
    rejected:已失敗

  1-----只有非同步操作的結果,可以決定Promise是哪一種狀態,任何其他操作都無法改變這個狀態

  2-----一旦Promise狀態改變,就不會再有變化,任何時候都可以得到這個結果。Promise物件的狀態改變,只有兩種可能:從pending變為fulfilled 或者 從pending變為rejected。只要這兩種情況發生,狀態就不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經發生了,你再對Promise物件添加回調函式,也會立即得到這個結果。這與事件(Event)不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的

    使用Promise的好處,就是在處理非同步程式時,將非同步操作佇列化,按照期望的順序執行,返回符合預期的結果,這樣即使是多重非同步操作,也可以方便的使用Promise進行鏈式呼叫

  3-----Promise也有一些缺點   

  首先,無法取消Promise,一旦新建它就會立即執行,無法中途取消。其次,如果不設定回撥函式,Promise內部丟擲的錯誤,不會反應到外部。第三,當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

第二部分、循序漸進的介紹Promise的用法


(2)promise狀態改變只有兩種情況
    從pending進行中變成fulfilled:已成功
    從pending進行中變成rejected: 已失敗


(3)promise中的非同步函式在建立的時候會預設執行
    * a. 非同步永遠都是無序的,這一點無法改變的
    * b. promise沒有改變非同步的順序,而是改變非同步的結果
    * c. 不要在建立promise的時候去操作非同步的結果,應該呼叫resolve在then方法種操作結果


(4)promise控制非同步操作順序的核心原理 : 在上一個promise的then方法中return下一個promise

 

 1 const fs = require('fs');
 2 
 3 //需求: (1)先讀取a  (2)然後讀取b (3)然後讀c  (4)最後讀取d
 4 
 5 //(1)例項化promise物件
 6 let p1 = new Promise((resolve,reject)=>{
 7     //非同步操作
 8     fs.readFile('./data/a.txt','utf8',(err,data)=>{
 9         if(!err){//成功執行的操作
10             /* 
11             (1)resolve() 呼叫then的第一個函式
12             (2)作用: 改變promise的狀態 從 從pending進行中變成fulfilled:已成功
13             */
14             resolve(data);
15             
16         }else{
17             /* 
18             (1)resolve() 呼叫then的第二個函式
19             (2)作用: 從pending進行中變成rejected: 已失敗
20             */
21             reject(err);
22         };
23     });
24 });
25 
26 let p2 = new Promise((resolve,reject)=>{
27     //非同步操作
28     fs.readFile('./data/b.txt','utf8',(err,data)=>{
29         if(!err){//成功執行的操作
30             resolve(data);
31         }else{
32             reject(err);
33         };
34     });
35 });
36 
37 let p3 = new Promise((resolve,reject)=>{
38     //非同步操作
39     fs.readFile('./data/c.txt','utf8',(err,data)=>{
40         if(!err){//成功執行的操作
41             resolve(data);
42         }else{
43             reject(err);
44         };
45     });
46 });
47 
48 //(2)呼叫promise例項的then方法
49 
50 p1.then(data=>{
51     console.log(data);   //這是p1的資料
52     return p2;//在p1的then方法中返回p2
53 })
54 .then(data=>{//呼叫p2的then方法
55     console.log(data);   //這是p2的資料
56     return p3;
57 })
58 .then(data=>{//呼叫p3的then方法
59     console.log(data);   //這是p3的資料
60 });
View Code

精闢個人總結:promise控制非同步順序的本質  不是控制非同步操作的本身 ,而是控制非同步操作的結果

Five、Promise的catch方法的使用:

catch作用: 捕捉promise的異常

 

 1 const fs = require('fs');
 2 
 3 //需求: (1)先讀取a  (2)然後讀取b (3)然後讀c  (4)最後讀取d
 4 
 5 function getPromise(fileName) {
 6     return new Promise((resolve, reject) => {
 7         //非同步操作
 8         fs.readFile(`./data/${fileName}.txt`, 'utf8', (err, data) => {
 9             if (!err) {//成功
10                 resolve(data);
11             } else {
12                 reject(err);
13             };
14         });
15     });
16 }
17 
18 /* catch作用: 捕捉promise的異常 */
19 
20 //(1)例項化promise物件
21 let p1 = getPromise('a');
22 let p2 = getPromise('b');
23 let p3 = getPromise('c');
24 
25 //(2)呼叫promise例項的then方法
26 p1.then(data=>{
27     console.log(data);
28     return p2;
29 }).then(data=>{
30     console.log(data);
31     return p3;
32 }).then(data=>{
33     console.log(data);
34 }).catch(err=>{
35     //上面所有的promise只要有任何一個出現錯誤,就會執行catch
36     console.log(err);
37 })
View Code

 

Six、Promise的all方法的使用:

all作用 :  將多個promise合併成一個promise,所有的promise執行完畢才會走then方法 (&&)

 1 const fs = require('fs');
 2 
 3 //需求: (1)先讀取a  (2)然後讀取b (3)然後讀c  (4)最後讀取d
 4 
 5 function getPromise(fileName) {
 6     return new Promise((resolve, reject) => {
 7         //非同步操作
 8         fs.readFile(`./data/${fileName}.txt`, 'utf8', (err, data) => {
 9             if (!err) {//成功
10                 resolve(data);
11             } else {
12                 reject(err);
13             };
14         });
15     });
16 }
17 
18 /* 1.catch作用: 捕捉promise的異常
19    2.all作用 :  將多個promise合併成一個promise,所有的promise執行完畢才會走then方法
20 */
21 
22 //(1)例項化promise物件
23 let p1 = getPromise('a');
24 let p2 = getPromise('b');
25 let p3 = getPromise('c');
26 
27 //多個promise合併成一個promise
28 let pAll = Promise.all([p1,p2,p3]);
29 
30 //(2)呼叫promise例項的then方法
31 pAll.then(data=>{
32     //所有的promise都執行完畢,data是一個數組,儲存每一個promise的操作結果
33     console.log(data);
34     return p2;
35 }).catch(err=>{
36     //上面所有的promise只要有任何一個出現錯誤,就會執行catch
37     console.log(err);
38 })
View Code

Seven、Promise的race方法的使用:

race作用:  將多個promise合併成一個promise,任意primise執行完畢就會走then方法  (||)

 1 //(1)例項化promise物件
 2 let p1 = getPromise('/ada/dada');
 3 let p2 = getPromise('b');
 4 let p3 = getPromise('c');
 5 
 6 //多個promise合併成一個promise
 7 let pAll = Promise.race([p1, p2, p3]);
 8 
 9 //(2)呼叫promise例項的then方法
10 Promise.race([p1, p2, p3]).then(data => {
11     //任意promise執行完畢就會走then,此時其他的promise不再執行
12     console.log(data);
13 }, (err) => {
14     console.log('有檔案錯誤');
15 })
View Code

 

喜歡分享,喜歡學習,這些確實是在遇到的問題中解決問題的個人總結,如果喜歡,請點個贊,也歡迎到下方評論,我們一起探討技術......

個人github地址請移步-->

 

 

&n