es6 深入淺出 之Promise的用法以及理解

. 前沿


小編一直在項目中使用promise,,但是對promise理解的不是很透徹,總是模棱兩可的,所以用的不是很得心應(yīng)手,最近幸得與空,好好總結(jié)學(xué)習(xí)一下,經(jīng)過研究總結(jié)下來,發(fā)現(xiàn)自己一下清晰了好多,不錯很有幫助,不過這里都是我自己的理解,可能還有一些不足的地方,還要多多學(xué)習(xí),以后還會更新不足的或者錯誤的地方。


. 一,首先說一下Promise的概念

Promise是異步編程的一種解決方案,說白了就是一個構(gòu)造函數(shù),他自己本身有race,all,reject,resolve這幾個方法,原型上有then,catch兩個方法。

二,Promise對象的特點:

  • 1, 對象的狀態(tài)不受外界影響,promise對象代表一個異步操作,它有三種狀態(tài),pending(進行中)、fulfilled(已成功)、rejected(已失敗)。只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài),這也是(承諾)這個名字的由來。
  • 2, 一旦狀態(tài)改變就不會在改變,任何時候都可以得到這個結(jié)果,promise對象狀態(tài)改變的過程只能是:從pending變?yōu)?code>fulfilled還有從pending變?yōu)?code>rejected.也就是說如果狀態(tài)發(fā)生上述變化后,狀態(tài)就不會在改變了,這個時候我們稱之為resolved已定型。
  • 3, 這就是與事件event不同的地方,事件是如果你錯過了,再去監(jiān)聽是得不到結(jié)果的。

三,Promise的用法:

  • 1, 首先它是一個構(gòu)造函數(shù),所以每當(dāng)我們new一個promise實例,就表示一個具體的異步操作,這個構(gòu)造函數(shù)里邊有兩個參數(shù),分別是:resolve(成功之后的回調(diào)函數(shù))reject(失敗之后的回調(diào)函數(shù))。
  • 2,所以說這個異步操作的結(jié)果就是失敗或者成功,兩者都需要回調(diào)函數(shù)reject/resolve返回,這里要注意的是跟之前的單純的回調(diào)函數(shù)不同,不能用return把操作結(jié)果返回。要用回調(diào)函數(shù),切記。
. 我個人覺得這玩意還是需要舉例子比較好理解一點。我在我的項目中寫了一個例子,用來理解promise,

接下來我們先new一個Promise對象

//我是在vue項目中
    mounted() {
        let textPromise = new Promise((resolve, reject) => {
            //這個時候我們做一些異步操作
            setTimeout(() => {
                console.log("執(zhí)行完成我測試的promise");
                resolve('這里的resolve是成功后的回調(diào)');
            }, 3000);

        });
    },

執(zhí)行上面的代碼,就會發(fā)現(xiàn)控制臺直接打出執(zhí)行完成我測試的promise

這里需要注意的是我只是new了一個對象,并沒有調(diào)用它,但是我寫在里邊的異步操作已經(jīng)執(zhí)行了,所以說當(dāng)我們使用Promise時,需要寫在一個函數(shù)中,在需要的時候再去運行這個函數(shù),舉個例子:

        <div  @click="shishi"></div>
methods:{
       shishi() {
          console.log("點擊方法被調(diào)用");
            this.promiseTest().then((data) => {
                console.log(data);
            })
        },
        promiseTest() {
            let textPromise = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise");
                    resolve('這里的resolve是成功后的回調(diào)');
                }, 3000);

            });
            return textPromise;
        },
}

看完上面的代碼是不是你自己就有了一些理解了

在promiseTest方法里邊 return textPromise;出來這個對象,那么接下來就可以在shishi()方法里邊使用Promise對象上的then和catch方法了,這里就表現(xiàn)出來promise的強大之處了。

  • 這個時候你就應(yīng)該有一些小小的領(lǐng)悟就是原來then里邊的函數(shù)跟我們平時的一個回調(diào)函數(shù)是一個意思,它接受resolve傳過來的數(shù)據(jù),可以在shishi這個點擊方法執(zhí)行完成之后在執(zhí)行textPromise的回調(diào)函數(shù)。
  • promise的好處就是當(dāng)有多層回調(diào)時,可以不斷的在then方法中繼續(xù)寫promise對象并返回,然后在then方法中進行回調(diào)操作。
所以說promise的精髓就是能夠簡化層層回調(diào),直接在后邊鏈式回調(diào)then,比你不斷的寫callback方法要好的多,也就達到了異步的效果。

所以說promise的正確應(yīng)用場景是

        <div  @click="shishi"></div>
        methods:{
          shishi() {
            this.promiseTest().then((data) => {
              //這里的data就是promiseTest中textPromise對象中resolve回調(diào)方法中返回的值
                console.log(data);
            //然后在這里在把this.promiseTestOne(data);的結(jié)果回調(diào)給下一個dataOne
        //這里如同回調(diào)函數(shù),把第二個的方法傳過去才會運行,如果在這里只return,data,那么打印的結(jié)果就是
          全是第一個promise里resolve('這里的resolve是成功后的回調(diào)');的值。
                return this.promiseTestOne(data);
            }, (reject) => {
                console.log(reject);   //這里就是錯誤的回調(diào),但是盡量不要寫在這里,而是寫在catch里
            }).then((dataOne) => {
                //這里的dataOne就是promiseTestOne中textPromise1對象中resolve回調(diào)方法中返回的值
                console.log(dataOne);
            }).then((data) =>{
                console.log(data);  //同樣這個data還是接受的上個promise中resolve回調(diào)的值
                console.log("前邊倆方法都調(diào)用成功后才會走這個");
            }).catch((data) => {
              //一般情況下你的方法出錯不會卡死,而是進入這里。
                console.log(data);   //catch就是用來捕獲異常的,所以一般錯誤都會在這里輸出日志
            })
        },
        promiseTest() {
            let textPromise = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise");
                    resolve('這里的resolve是成功后的回調(diào)');
                  //下邊這段代碼會執(zhí)行在reject或者catch中
                    let a = 10;
                    if (a == 10) {
                        reject('這里的reject是失敗后的回調(diào)');
                    }
                }, 3000);

            });
            return textPromise;

        },
        promiseTestOne(data) {
           //data是接受的第一個promise中的回調(diào)值,方便這個promise使用
            console.log("我是第二個方法" + data + "data 是從promiseTest 的resolve 回調(diào)傳過來的值");
            let textPromise1 = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise  測試11");
                    resolve('這里的resolve是成功后的回調(diào)' + '測試1');
                }, 3000);

            });
            return textPromise1;
        },
}

以上寫法就達到了你想在某個接口完全完成之后在調(diào)用下一個接口,也就是異步調(diào)用,而不是像你之前那樣,同步的調(diào)用接口。

其實上邊的代碼跟注釋就一同解釋了promiserejectresolve、then、catch、這幾個方法

接下來說一下all方法,all是跟then方法同級的一個方法,該方法提供了并行執(zhí)行(也就是多個方法可以共存并且同時執(zhí)行)異步操作的能力,就是說在所有的異步操作執(zhí)行完成后并且都是成功的情況下才會執(zhí)行回調(diào)。
  • 也就是說all方法不適合我上邊舉的例子,all方法適合在多個互不相關(guān)的方法需要同時執(zhí)行成功后在執(zhí)行某方法時使用
    shishi() {
            Promise.all([this.promiseTest(),this.promiseTestOne()]).then((allResult) => {
                  console.log(allResult);
                  console.log("所有的異步操作執(zhí)行完成后并且都是成功的情況下才會執(zhí)行回調(diào)");
            }).catch((catchResult)=>{
                  console.log(catchResult);
                })
        },
        promiseTest() {
            let textPromise = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise")
                    resolve('這里的resolve是成功后的回調(diào)');
                }, 3000);

            });
            return textPromise;
        },
        promiseTestOne() {
            let textPromise1 = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise  測試11");
                    resolve('這里的resolve是成功后的回調(diào)' + '測試1');
                }, 3000);

            });
            return textPromise1;
        },

里邊的注釋看完是不是一目了然。

最后再說一下不常用的race方法

race其實是和all是相反的,就是誰先執(zhí)行完,就先走誰的回調(diào),舉個例子,一目了然

注意我把異步的時間改一下

    shishi() {
            Promise.race([this.promiseTest(),this.promiseTestOne()]).then((allResult) => {
                  console.log(allResult);
                  console.log("誰先執(zhí)行完,就先走誰的回調(diào)");
            }).catch((catchResult)=>{
                  console.log(catchResult);
                })
        },
        promiseTest() {
            let textPromise = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise")
                    resolve('這里的resolve是成功后的回調(diào)');
                }, 2000);

            });
            return textPromise;
        },
        promiseTestOne() {
            let textPromise1 = new Promise((resolve, reject) => {
                //這個時候我們做一些異步操作
                setTimeout(() => {
                    console.log("執(zhí)行完成我測試的promise  測試11");
                    resolve('這里的resolve是成功后的回調(diào)' + '測試1');
                }, 5000);

            });
            return textPromise1;
        },

上面的代碼執(zhí)行結(jié)果就是2秒的先執(zhí)行完畢就已經(jīng)進入到then里面的了,而于此同時,promiseTestOne也就是5秒的并沒有停止,還在運行,于是在過三秒后,輸出了各自的回調(diào)值。

結(jié)束語

最后再說一下,race方法的用法,小編很少用到,所以等慢慢接觸到在更新,目前常用的5種。

最后編輯于
?著作權(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)容

  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點點福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運大...
    HetfieldJoe閱讀 8,780評論 0 29
  • 一、前言 前端面試過程中,基本都會問到 Promise,如果你足夠幸運,面試官問的比較淺,僅僅問 Promise ...
    懿左左閱讀 42,224評論 0 29
  • 你不知道JS:異步 第三章:Promises 接上篇3-1 錯誤處理(Error Handling) 在異步編程中...
    purple_force閱讀 1,498評論 0 2
  • 什么是Promise fetchX() 和fetchY() 是直接調(diào)用的,它們的返回值(promise!)被傳給a...
    xpwei閱讀 2,619評論 0 6
  • 透過蒙蒙細雨,遙望遙遠的前方,雨滴相互交錯,透過雨滴看著朦朧的景色。冥想歲月沉淀的以往,再也看不清摸不著,幾經(jīng)落花...
    素健閱讀 330評論 0 0

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