Promise初步詳解(resolve,reject,catch)


一:何為Promise?

為了直觀一點,首先我們采用console.dir(Promise)看一下它的結構組成。

從上面的圖片中我們可以到,Promise其實是一個構造函數,它有resolve,reject,race等靜態方法;它的原型(prototype)上有then,catch方法,因此只要作為Promise的實例,都可以共享並調用Promise.prototype上面的方法(then,catch),接下來我們試着使用一下Promise。

二:Promise的使用


首先我們來看一下Promise的使用語法:

new Promise(function(resolve,reject){}/*excutor*/);

在實例化Promise時需要傳入一個函數excutor作為參數,並且在Promise構造函數執行時同步執行。廢話不多說,先看一個簡單的實例:

   var p = new Promise(function(resolve,reject){
                var timer = setTimeout(function(){
                    console.log('執行操作1');
                },1000);
            });

我們可以看到1s后在控制台輸出相應的結果,這就說明在實例化過程中,作為參數的excutor函數也會執行。

從上面的實例中我們看到,excutor函數還有兩個參數resolve和reject,其實這兩個參數也是函數,在excutor執行時被調用,下面我們具體來談談resolve和reject的用法。

三:resolve和reject的具體用法

1.先來說說resolve的用法

首先我們來看看Promise的幾種狀態:

pending: 初始狀態,成功或失敗狀態。

fulfilled: 意味着操作成功完成。

rejected: 意味着操作失敗。

當我們在excutor函數中調用resolve方法時,Promise的狀態就變成fulfilled,即操作成功狀態,還記得上面Promise.prototype上面的then和catch方法嗎?當Promise狀態為fullfilled狀態時執行then方法里的操作,注意了,then方法里面有兩個參數onfulfilled(Promise為fulfilled狀態時執行) 和onrejected(Promise為rejected狀態時執行),步驟如下:

1.實例化Promise(new Promise(function(resolve,reject)))

2.用Promise的實例調用then方法。

具體來看下面的例子:

    var p = new Promise(function (resolve, reject) {
                var timer = setTimeout(function () {
                    console.log('執行操作1');
                    resolve('這是數據1');
                }, 1000);
            });
            p.then(function (data) {
                console.log(data);
                console.log('這是成功操作');
            });

簡單的理解就是調用resolve方法,Promise變為操作成功狀態(fulfilled),執行then方法里面onfulfilled里的操作。其實then里面的函數就是我們平時所說的回調函數,只不過在這里只是把它分離出來而已。我們可以看到控制台上的輸出結果如下所示:

2.reject的用法

看了上面的實例,我相信應該也很容易理解reject方法了,就是調用reject方法后,Promise狀態變為rejected,即操作失敗狀態,此時執行then方法里面onrejected操作,上面我們提到了then方法有兩個參數,一種是Promise狀態為fulfilled時執行(onfullfilled),一種是Promise狀態為rejected時執行(onrejected),其實就是類似於jquery里的hover方法里面的兩個參數一樣,來看看下面的例子:

    var p = new Promise(function (resolve, reject) {
              var flag = false;
              if(flag){
                resolve('這是數據2');
              }else{
                reject('這是數據2');
              }
            });
            p.then(function(data){//狀態為fulfilled時執行
                console.log(data);
                console.log('這是成功操作');
            },function(reason){ //狀態為rejected時執行
                console.log(reason);
                console.log('這是失敗的操作');
            });

 我們可以看到輸出結果:

三:catch方法

我們注意到除了then方法外,Promise原型上還有另外一個叫catch的方法,那么這個方法的作用是什么呢?其實跟then方法中的第二個參數一樣,就是在Promise狀態為rejected時執行,then方法捕捉到Promise的狀態為rejected,就執行catch方法里面的操作,下面用catch方法改寫上面reject用法里面的例子,如下所示:

  var p = new Promise(function (resolve, reject) {
              var flag = false;
              if(flag){
                resolve('這是數據2');
              }else{
                reject('這是數據2');
              }
            });
            p.then(function(data){
                console.log(data);
                console.log('這是成功操作');
            }).catch(function(reason){
                console.log(reason);
                console.log('這是失敗的操作');
            });

執行結果和上面reject用法的例子一樣。

四.為何用Promise

首先我們來看這樣一個例子,取4個定時器,設置延遲時間都為1s,然后每隔1s依次在控制台輸出‘我’‘愛’‘米’‘飯’的字樣。代碼如下:

      setTimeout(function () {
                console.log('我');
                setTimeout(function () {
                    console.log('愛');
                    setTimeout(function () {
                        console.log('米');
                        setTimeout(function () {
                            console.log('飯');
                        }, 1000);
                    }, 1000);
                }, 1000);
            }, 1000);

發現什么問題沒有?是不是有點感覺回調函數的嵌套有點多,如果有更多的回調函數呢?是不是使代碼的可讀性和可維護性都大大降低了呢(回調地獄?),這時如果我們使用Promise去實現這個效果,雖然可能代碼不會減少,甚至更多,但是卻大大增強了其可讀性和可維護性。具體看下面例子:

            function getStr1() {
                return new Promise(function (resolve, reject) {
                    setTimeout(function () {
                        resolve('我');
                    }, 1000);
                });
            }
            function getStr2() {
                return new Promise(function (resolve, reject) {
                    setTimeout(function () {
                        resolve('愛');
                    }, 1000);
                });
            }
            function getStr3() {
                return new Promise(function (resolve, reject) {
                    setTimeout(function () {
                        resolve('米');
                    }, 1000);
                });
            }
            function getStr4() {
                return new Promise(function (resolve, reject) {
                    setTimeout(function () {
                        resolve('飯');
                    }, 1000);
                });
            }
            getStr1().then(function (data) {
                console.log(data);
                return getStr2();
            }).then(function (data) {
                console.log(data);
                return getStr3();
            }).then(function (data) {
                console.log(data);
                return getStr4();
            }).then(function (data) {
                console.log(data);
            })

執行效果跟上面一樣,在這個例子中,將得到Promise實例的過程封裝成一個函數(getStr1,getStr2,getStr3,getStr4)並返回一個Promise實例,再用實例去調用相應的then方法,在每個then方法中通過return得到下一級的Promise實例,比如在第一個Promise實例(getStr1())then方法中,通過return返回下一個Promise對象(getStr2()),然后再去調用then方法執行里面的操作,再返回下一個Promise對象(這里是getStr3()),這樣一級一級下去實現了鏈式調用,雖然代碼量增加了,但比起前面的層層嵌套,顯然這種方式使得代碼更易讀更易維護。

本文對Promise的介紹就到這里,歡迎大家指正里面的錯誤和不准確的地方。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM