ES6 promise

今天我說下我所理解的prosime,prosime是ES6的構造函數,里面有很多方法,我們之間打印一下promise

Paste_Image.png

它里面有許多方法,等會我們會一一說到。
首先,它有什么用,我們先new 一個看看

var p = new Promise(function(resolve, reject){
    //做一些異步操作
    setTimeout(function(){
        console.log('執行完成');
        resolve('隨便什么數據');
    }, 2000);
});

promise的構造函數接收一個參數,是一個函數,并且有兩個參數:resolve,seject,分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。
在上面一串代碼中,我們執行了一個異步操作,也就是seTimeout,2秒后,輸出“執行完成”,并且調用resolve方法。
運行代碼,會在2秒后輸出“執行完成”,注意我在這里只是new了一個對象,并沒有調用它,我們傳進去的函數就已經執行了,這是一個需要注意的細節,所以我們用promise的時候要把它包在一個函數里面如:

function runAsync(){
    var p = new Promise(function(resolve, reject){
        //做一些異步操作
        setTimeout(function(){
            console.log('執行完成');
            resolve('隨便什么數據');
        }, 2000);
    });
    return p;            
}
runAsync()

現在你應該有疑問,這個函數是有什么用,resolve又有什么用。
我們寫好的函數最后會return出一個promise對象,也就是說我們最后會得到這么一個對象,還記得我們剛開始打印的一些方法么,加上這些方法,它就會很強大。

    function runAsync1(){
                var p = new Promise(function(resolve, reject){
                    //做一些異步操作
                    setTimeout(function(){
                        console.log('執行完成');
                        resolve('隨便一些數據');
                    }, 1000);
                });
                return p;            
            }
            runAsync1()
            .then(function(results){
                console.log(results);
            });

這時它會先輸出執行完成,在輸出隨便一些數據,也就是在上面函數執行完了之后,就會執行下面then里面的函數,當然它也是可以回調方法的

function runAsync1(){
                var p = new Promise(function(resolve, reject){
                    //做一些異步操作
                    setTimeout(function(){
                        console.log('執行完成');
                        resolve(function(){
                            alert(1234598)
                        });
                    }, 1000);
                });
                return p;            
            }
            runAsync1()
            .then(function(results){
                results();
            });

你可能會說這東西有什么用,這不就是一個回調函數么,那么問題來了,有多層回調怎么辦?如果回調函數也是一個異步操作,而且執行完,也需要一個相應的回調函數怎么辦?promise的優勢在于,可以在then方法中繼續寫一個promise對象并返回,然后繼續調用then的回調,好比這樣

    function runAsync1(){
                var p = new Promise(function(resolve, reject){
                    //做一些異步操作
                    setTimeout(function(){
                        console.log('執行完成');
                        resolve('隨便一些數據');
                    }, 1000);
                });
                return p;            
            }
            function runAsync2(){
                var p = new Promise(function(resolve, reject){
                    //做一些異步操作
                    setTimeout(function(){
                        console.log('執行完成2');
                        resolve('隨便一些數據2');
                    }, 2000);
                });
                return p;            
            }
            function runAsync3(){
                var p = new Promise(function(resolve, reject){
                    //做一些異步操作
                    setTimeout(function(){
                        console.log('執行完成3');
                        resolve('隨便一些數據3');
                    }, 2000);
                });
                return p;            
            }
            runAsync1()
            .then(function(data){
                console.log(data);
                return runAsync2();
            })
            .then(function(data){
                console.log(data);
                return runAsync3();
            })
            .then(function(data){
                console.log(data);
});

它會先后輸出


Paste_Image.png

在then方法中,你也可以直接return數據而不是一個promise對象,在后面then中就可以接受數據啦,比如我們把上面的代碼修改成這樣:

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return '直接返回數據';  //這里直接返回數據
})
.then(function(data){
    console.log(data);
});

那么輸出結果就變成了

Paste_Image.png

說了這么多,基本對promise對象有了基本的了解,接下來我們看看他還有什么功能,我們光用了resolve,還沒有用reject,它是做什么的呢?事實上,我們前面的例子中只有“執行成功”的回調,還沒有“返回失敗”的回調,reject的作用就是把promise的狀態置為rejected,這樣我們在then中就可以捕捉到了,然后執行“失敗”的回調,看一下代碼

   function getNumber(){
    var p = new Promise(function(resolve, reject){
        //做一些異步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的隨機數
            if(num<=5){
                resolve(num);
            }
            else{
                reject('數字太大了');
            }
        }, 2000);
    });
    return p;            
}
getNumber()
.then(
    function(data){
        console.log('resolved');
        console.log(data);
    }, 
    function(reason){
        console.log('rejected');
        console.log(reason);
    }
);

我們在函數中生成一個1--10的隨機數,如果它小于等于5,那么讓它在成功中輸出這個數字,如果他大于5,那么讓它在失敗中輸出“數字太大啦”,在then的方法中有兩個參數,一個是成功的回調方法,一個是失敗的回調方法,多次執行,它就會有時輸出小于5的數字,有時輸出“數字太大了”.
catch的用法
我們知道promise中除了then方法,還有catch方法,它有什么用,其實它和then的第二個參數是一樣的,用來指定reject的回調,用法是這樣

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

效果和寫在then的第二個參數里面一樣,不過它還有另一個作業:在執行resolve的時候(也就是then的第一個參數)時,如果拋出異常啦(代碼出錯啦),那么并不會報錯卡死js,而是到這個catch方法中

all的用法

promise的all方法提供了并行執行異步操作的能力,并且在所有異步操作執行完回調。我們依舊使用上面定義好的runAsync1、runAsync2、runAsync3這3個方法,看以下代碼

Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

用promise的all來執行,all接收一個數組參數,里面的值最終都算返回promise對象。這樣,三個異步操作的并行執行的,等到他們都執行完之后才會放到then里面。那么,三個異步操作返回的數據到哪里去啦呢?都在then里面,all會吧所有異步操作的結果放在一個數組中傳給then,就是上面的results。所以上面代碼輸出的結果就是:

Paste_Image.png

有了all,你就可以并行執行多個異步操作,并且在一個回調中處理所有的返回數據。

race的用法
all方法的效果實際上是「誰跑的慢,以誰為準執行回調」,那么相對的就有另一個方法「誰跑的快,以誰為準執行回調」,這就是race方法,這個詞本來就是賽跑的意思。race的用法與all一樣,我們把上面runAsync1的延時改為1秒來看一下:

Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

這三個異步操作同樣是并行執行的。結果你應該可以猜到,1秒后runAsync1已經執行完了,此時then里面的就執行了。結果是這樣的:

Paste_Image.png

這個race有什么用呢?使用場景還是很多的,比如我們可以用race給某個異步請求設置超時時間,并且在超時后執行相應的操作,代碼如下:

//請求某個圖片資源
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函數會異步請求一張圖片,我把地址寫為"xxxxxx",所以肯定是無法成功請求到的。timeout函數是一個延時5秒的異步操作。我們把這兩個返回Promise對象的函數放進race,于是他倆就會賽跑,如果5秒之內圖片請求成功了,那么遍進入then方法,執行正常的流程。如果5秒鐘圖片還未成功返回,那么timeout就跑贏了,則進入catch,報出“圖片請求超時”的信息。運行結果如下:


Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • Promise的含義: ??Promise是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和...
    呼呼哥閱讀 2,187評論 0 16
  • 如果瀏覽已經有了Promise對象,那么頁就說明瀏覽器的js引擎里已經有了Promsise隊列,這樣就可以利用Pr...
    羊烊羴閱讀 518評論 0 0
  • 特點 Promise能將回調分離出來,在異步操作執行之后,用鏈式方法執行回調,雖然es5用封裝函數也能實現,但是如...
    一二三kkxx閱讀 629評論 0 1
  • //本文內容起初摘抄于 阮一峰 作者的譯文,用于記錄和學習,建議觀者移步于原文 概念: 所謂的Promise,...
    曾經過往閱讀 1,246評論 0 7
  • 本文適用的讀者 本文寫給有一定Promise使用經驗的人,如果你還沒有使用過Promise,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,322評論 6 19