es6 Promise對象

本文是本人學(xué)習(xí)時遇到Promise后,在網(wǎng)上查詢資料及總結(jié)后的學(xué)習(xí)筆記。

什么是Promise?

看看MDN的定義:
原文請點擊

Promise 對象用于一個異步操作的最終完成(或失?。┘捌浣Y(jié)果值的表示。(簡單點說就是處理異步請求。。我們經(jīng)常會做些承諾,如果我贏了你就嫁給我,如果輸了我就嫁給你之類的諾言。這就是promise的中文含義。一個諾言,一個成功,一個失敗。)

我們再看看在控制臺上Promise長什么樣?

image.png

我們簡單總結(jié)一下:
1.Promise是一個構(gòu)造函數(shù),可以異步操作。
2.可以根據(jù)異步處理結(jié)果進行不同處理(success/error)
3.它包含了一些方法,(catch,then,reject,resolve...)

既然提及了根據(jù)不同異步結(jié)果,會有不同處理方法,那么我們?nèi)绾沃滥兀?br> 就是根據(jù)狀態(tài),沒錯,Promise就是根據(jù)狀態(tài)來識別該如何處理的。

一個 Promise有以下幾種狀態(tài):

  • pending: 初始狀態(tài),不是成功或失敗狀態(tài)。
  • fulfilled: 意味著操作成功完成。
  • rejected: 意味著操作失敗。
image.png

而且Promise不能被重置,只能設(shè)置一次。
Once settled, a promise can not be resettled. Calling resolve() or reject() again will have no effect. The immutability of a settled promise is an important feature.

Promise怎么用

resolve用法

var myFirstPromise = new Promise(function(resolve, reject){
    //當(dāng)異步代碼執(zhí)行成功時,我們才會調(diào)用resolve(...), 當(dāng)異步代碼失敗時就會調(diào)用reject(...)
    //在本例中,我們使用setTimeout(...)來模擬異步代碼,實際編碼時可能是XHR請求或是HTML5的一些API方法.
    setTimeout(function(){
        resolve("成功!"); //代碼正常執(zhí)行!
    }, 250);
});

myFirstPromise.then(function(successMessage){
    //successMessage的值是上面調(diào)用resolve(...)方法傳入的值.
    //successMessage參數(shù)不一定非要是字符串類型,這里只是舉個例子
    console.log("Yay! " + successMessage);
});
  • 邏輯處理完畢并且沒有錯誤時,resolve這個回調(diào)會將值傳遞到一個特殊的地方。這個特殊的地方在哪呢?就是下面代碼中的then,我們使用then中的回調(diào)函數(shù)來處理resolve后的結(jié)果。比如上面的代碼中,我們將值簡單的輸出到控制臺。如果有錯誤,則reject到then的第二個回調(diào)函數(shù)中,對錯誤進行處理。

  • 注意!我只是new了一個對象,并沒有調(diào)用它,我們傳進去的函數(shù)就已經(jīng)執(zhí)行了,這是需要注意的一個細節(jié)。所以我們用Promise的時候一般是包在一個函數(shù)中,在需要的時候去運行這個函數(shù),如:

function p() {
    var myFirstPromise = new Promise(function (resolve, reject) {    
        setTimeout(function () {
            resolve("成功!"); //代碼正常執(zhí)行!
        }, 250);
    });
    return myFirstPromise
}
p().then(function (successMessage) {
    console.log("Yay! " + successMessage);
});

那我們返回的這個myFirstPromise有什么用呢?就是可以接著用then(),catch()等方法,這是Promise的精髓。
這和我們以前使用回調(diào)函數(shù)是相同的,有什么特殊呢?

function runAsync(callback){
    setTimeout(function(){
        console.log('執(zhí)行完成');
        callback('隨便什么數(shù)據(jù)');
    }, 2000);
}

runAsync(function(data){
    console.log(data);
});

那么問題來了,有多層回調(diào)該怎么辦?如果callback也是一個異步操作,而且執(zhí)行完后也需要有相應(yīng)的回調(diào)函數(shù),該怎么辦呢?總不能再定義一個callback2,然后給callback傳進去吧。而Promise的優(yōu)勢在于,可以在then方法中繼續(xù)寫Promise對象并返回,然后繼續(xù)調(diào)用then來進行回調(diào)操作。

用Promise我們可以這么寫。

function runAsync1(){
    var p = new Promise(function(resolve, reject){
        //做一些異步操作
        setTimeout(function(){
            console.log('異步任務(wù)1執(zhí)行完成');
            resolve('隨便什么數(shù)據(jù)1');
        }, 1000);
    });
    return p;            
}
function runAsync2(){
    var p = new Promise(function(resolve, reject){
        //做一些異步操作
        setTimeout(function(){
            console.log('異步任務(wù)2執(zhí)行完成');
            resolve('隨便什么數(shù)據(jù)2');
        }, 2000);
    });
    return p;            
}
function runAsync3(){
    var p = new Promise(function(resolve, reject){
        //做一些異步操作
        setTimeout(function(){
            console.log('異步任務(wù)3執(zhí)行完成');
            resolve('隨便什么數(shù)據(jù)3');
        }, 2000);
    });
    return p;            
}


runAsync1()//return a Promise object
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return runAsync3();
})
.then(function(data){
    console.log(data);
});

結(jié)果如下:

image.png

當(dāng)然,直接返回數(shù)據(jù)也可以類似在函數(shù)里寫入resolve(''),傳給下面的回調(diào)函數(shù)。

          runAsync1()
            .then(function (data) {
                console.log(data);
                return '直接傳數(shù)據(jù)';
            })
            .then(function (data) {
                console.log(data);
                return runAsync3();
            })
            .then(function (data) {
                console.log(data);
            });

結(jié)果:

image.png

reject用法

接下來說說reject用法.
reject的作用就是把Promise的狀態(tài)置為rejected,這樣我們在then中就能捕捉到,然后執(zhí)行‘失敗’函數(shù)(此時我們調(diào)用的時then()傳入的第二個函數(shù))。所以這個狀態(tài)是我們標(biāo)記的。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        function getNumber() {
            var p = new Promise(function (resolve, reject) {
                //做一些異步操作
                setTimeout(function () {
                    var num = Math.ceil(Math.random() * 10); //生成1-10的隨機數(shù)
                    if (num <= 5) {
                        resolve(num);
                    } else {
                        reject('數(shù)字是'+num+',太大了');
                    }
                }, 2000);
            });
            return p;
        }

        getNumber()
            .then(
                function (data) {
                    console.log('resolved');
                    console.log(data);
                },
                function (reason, data) {
                    console.log('rejected');
                    console.log(reason);
                }
            );
    </script>
</body>

</html>

結(jié)果

image.png

catch用法

我們知道Promise對象除了then方法,還有一個catch方法,它是做什么用的呢?其實它和then的第二個參數(shù)一樣,用來指定reject的回調(diào),用法是這樣:

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

這和我們上面在then里傳入第二個函數(shù)效果是一樣的。
不過它還有另外一個作用:在執(zhí)行resolve的回調(diào)(也就是上面then中的第一個參數(shù))時,如果拋出異常了(代碼出錯了),那么并不會報錯卡死js,而是會進到這個catch方法中。請看下面的代碼:

getNumber()
.then(function(data){
   console.log('resolved');
   console.log(data);
   console.log(somedata); //此處的somedata未定義
})
.catch(function(reason){
   console.log('rejected');
   console.log(reason);
}).then(function(){
   console.log('試著能不能繼續(xù)運行')
});

結(jié)果

image.png

我們看到第一個回調(diào)運行時產(chǎn)生錯誤以后,會把錯誤拋給catch(),然后處理后后面的程序會繼續(xù)運行,而不會停止。這是catch的好處.
否則會直接在控制臺報錯,后面也停止了。

image.png

all的用法

Promise的all方法提供了并行執(zhí)行異步操作的能力,并且在所有異步操作執(zhí)行完后才執(zhí)行回調(diào)。我們?nèi)耘f使用上面定義好的runAsync1、runAsync2、runAsync3這三個函數(shù),看下面的例子:

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

結(jié)果

image.png

可以看到,我們把三個函數(shù)并行執(zhí)行時,把各自返回的結(jié)果存在一個數(shù)組里,再把這個數(shù)組作為參數(shù),傳遞給then。

以上~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Promise的含義: ??Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和...
    呼呼哥閱讀 2,262評論 0 16
  • 前言 在Promise之前,js的異步編程都是采用回調(diào)函數(shù)和事件的方式。但是這種編程方式在處理復(fù)雜業(yè)務(wù)的情況下,很...
    卓三陽閱讀 912評論 0 1
  • 1. 首先創(chuàng)建Promise實例,Promise實例生成以后,可以用then方法分別指定Resolved狀態(tài)和Re...
    竹溪穆褕閱讀 506評論 0 2
  • Promiese 簡單說就是一個容器,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果,語法上說,Pr...
    雨飛飛雨閱讀 3,484評論 0 19
  • 紅旗獵獵京城風(fēng),鐮斧再造新里程。 國富民安迎盛境,高新科技不松懈。 倡廉反腐入民心,環(huán)球氣勢誰爭鋒? 華夏子孫頌歌...
    付小之閱讀 202評論 0 0

友情鏈接更多精彩內(nèi)容