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構造函數執行時同步執行。廢話不多說,先看一個簡單的實例:


 
  1. var p = new Promise(function(resolve,reject){

  2.              var timer = setTimeout(function(){

  3.                  console.log('執行操作1');

  4.              },1000);

  5.          });

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

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


三,resolve和reject的具體用法

先來說說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方法

具體來看下面的例子:


 
  1. var p = new Promise(function (resolve, reject) {

  2.             var timer = setTimeout(function () {

  3.                 console.log('執行操作1');

  4.                 resolve('這是數據1');

  5.             }, 1000);

  6.         });

  7.         p.then(function (data) {

  8.             console.log(data);

  9.             console.log('這是成功操作');

  10.         });

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


reject的用法

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


 
  1. var p = new Promise(function (resolve, reject) {

  2.           var flag = false;

  3.           if(flag){

  4.             resolve('這是數據2');

  5.           }else{

  6.             reject('這是數據2');

  7.           }

  8.         });

  9.         p.then(function(data){//狀態爲fulfilled時執行

  10.             console.log(data);

  11.             console.log('這是成功操作');

  12.         },function(reason){ //狀態爲rejected時執行

  13.             console.log(reason);

  14.             console.log('這是失敗的操作');

  15.         });

 我們可以看到輸出結果:


catch方法

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


 
  1. var p = new Promise(function (resolve, reject) {

  2.             var flag = false;

  3.             if(flag){

  4.               resolve('這是數據2');

  5.             }else{

  6.               reject('這是數據2');

  7.             }

  8.           });

  9.           p.then(function(data){

  10.               console.log(data);

  11.               console.log('這是成功操作');

  12.           }).catch(function(reason){

  13.               console.log(reason);

  14.               console.log('這是失敗的操作');

  15.           });

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

 


爲什麼會有promise,他的作用是什麼?

promise主要是爲了解決js中多個異步回調難以維護和控制的問題.

四,爲何用Promise

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


 
  1. setTimeout(function () {

  2.           console.log('我');

  3.           setTimeout(function () {

  4.               console.log('愛');

  5.               setTimeout(function () {

  6.                   console.log('米');

  7.                   setTimeout(function () {

  8.                       console.log('飯');

  9.                   }, 1000);

  10.               }, 1000);

  11.           }, 1000);

  12.       }, 1000);

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


 
  1. function getStr1() {

  2.     return new Promise(function (resolve, reject) {

  3.         setTimeout(function () {

  4.             resolve('我');

  5.         }, 1000);

  6.     });

  7. }

  8. function getStr2() {

  9.     return new Promise(function (resolve, reject) {

  10.         setTimeout(function () {

  11.             resolve('愛');

  12.         }, 1000);

  13.     });

  14. }

  15. function getStr3() {

  16.     return new Promise(function (resolve, reject) {

  17.         setTimeout(function () {

  18.             resolve('米');

  19.         }, 1000);

  20.     });

  21. }

  22. function getStr4() {

  23.     return new Promise(function (resolve, reject) {

  24.         setTimeout(function () {

  25.             resolve('飯');

  26.         }, 1000);

  27.     });

  28. }

  29. getStr1().then(function (data) {

  30.     console.log(data);

  31.     return getStr2();

  32. }).then(function (data) {

  33.     console.log(data);

  34.     return getStr3();

  35. }).then(function (data) {

  36.     console.log(data);

  37.     return getStr4();

  38. }).then(function (data) {

  39.     console.log(data);

  40. })

執行效果跟上面一樣,在這個例子中,將得到Promise實例的過程封裝成一個函數(getStr1,getStr2,getStr3,getStr4)並返回一個Promise實例,再用實例去調用相應的then方法,在每個then方法中通過return得到下一級的Promise實例,比如在第一個Promise實例(getStr1())then方法中,通過return返回下一個Promise對象(getStr2()),然後再去調用then方法執行裏面的操作,再返回下一個Promise對象(這裏是getStr3()),

這樣一級一級下去實現了鏈式調用,雖然代碼量增加了,但比起前面的層層嵌套,顯然這種方式使得代碼更易讀更易維護。


小例子:


 
  1. function checkFunc() {

  2. let p = new Promise(function (resolve, reject) {

  3. // 一些比較耗時異步操作

  4. if(操作完成標識) {

  5. resolve();

  6. }

  7. });

  8. p.then(function (data) {

  9. layer.confirm('執行下一步操作?', {

  10. btn: ['確定', '取消']

  11. }, function () {

  12. // 確保上面的操作都完成後,才執行下面的操作

  13. // 其他操作...

  14. });

  15. });

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章