官术网_书友最值得收藏!

1.5.3 Promise和async/await

1.Promise

Promise是一種適用于異步操作的機(jī)制,比傳統(tǒng)的回調(diào)函數(shù)解決方案更合理和更強(qiáng)大。從語(yǔ)法上說(shuō),Promise是一個(gè)對(duì)象,從它可以獲取異步操作的結(jié)果:成功或失敗。在Promise中,有三種狀態(tài):pending(進(jìn)行中)、resolved(已成功)和rejected(已失敗)。只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài),無(wú)法被Promise之外的方式改變。這也是Promise這個(gè)名字的由來(lái),它的英語(yǔ)意思就是“承諾”,表示其他手段無(wú)法改變。創(chuàng)建一個(gè)Promise對(duì)象,代碼如下:

     var promise = new Promise(function(resolve, reject) {
       ...
       if (/* 異步操作成功 */){
         resolve(value);
       } else {
         reject(error);
       }
     });

在上面的代碼中,創(chuàng)建了一個(gè)Promise對(duì)象,Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolve和reject。這是兩個(gè)內(nèi)置函數(shù),resolve函數(shù)的作用是將Promise對(duì)象的狀態(tài)變?yōu)椤俺晒Α保诋惒讲僮鞒晒r(shí)調(diào)用,并將異步操作的結(jié)果作為參數(shù)傳遞出去;reject函數(shù)的作用是將Promise對(duì)象的狀態(tài)變?yōu)椤笆 保诋惒讲僮魇r(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤作為參數(shù)傳遞出去。當(dāng)代碼中出現(xiàn)錯(cuò)誤(Error)時(shí),就會(huì)調(diào)用catch回調(diào)方法,并將錯(cuò)誤信息作為參數(shù)傳遞出去。

Promise對(duì)象實(shí)例生成后,可以用then方法分別指定resolved(成功)狀態(tài)和rejected(失敗)狀態(tài)的回調(diào)函數(shù)以及catch方法,比如:

     promise.then(function(value) {
       // success邏輯
     }, function(error) {
       // failure邏輯
     }).catch(function(){
       // error邏輯
     });

then()方法返回的是一個(gè)新的Promise實(shí)例(不是原來(lái)那個(gè)Promise實(shí)例)。因此,可以采用鏈?zhǔn)綄?xiě)法,即then()方法后面再調(diào)用另一個(gè)then()方法,比如:

     getJSON("/1.json").then(function(post) {
       return getJSON(post.nextUrl);
     }).then(function (data) {
       console.log("resolved: ", data);
     }, function (err){
       console.log("rejected: ", err);
     });

下面是一個(gè)用Promise對(duì)象實(shí)現(xiàn)的Ajax操作get方法的例子。

     var getJSON = function(url) {
       // 返回一個(gè)Promise對(duì)象
       var promise = new Promise(function(resolve, reject){
         var client = new XMLHttpRequest(); //創(chuàng)建XMLHttpRequest對(duì)象
         client.open("GET", url);
         client.onreadystatechange = onreadystatechange;
         client.responseType = "json";              //設(shè)置返回格式為json
         client.setRequestHeader("Accept", "application/json");//設(shè)置發(fā)送格式為json
         client.send();//發(fā)送
         function onreadystatechange() {
           if (this.readyState !== 4) {
             return;
           }
           if (this.status === 200) {
             resolve(this.response);
           } else {
             reject(new Error(this.statusText));
           }
         };
       });
       return promise;
     };
     
     getJSON("/data.json").then(function(data) {
       console.log(data);
     }, function(error) {
       console.error(error);
     });

了解Promise的基本知識(shí)可以便于后續(xù)學(xué)習(xí)使用服務(wù)端渲染。當(dāng)然,Promise的應(yīng)用場(chǎng)合還是比較多的,如果想要深入了解,可以訪問(wèn)網(wǎng)址:https://developer.mozilla.org/en-US/docs/Web/Java Script/Reference/Global_Objects/Promise,進(jìn)行系統(tǒng)的學(xué)習(xí)。

2.a(chǎn)sync/await

async/await語(yǔ)法在2016年就已經(jīng)提出來(lái)了,屬于ES 7中的一個(gè)測(cè)試標(biāo)準(zhǔn)(目前來(lái)看是直接跳過(guò)ES 7,列為ES 8的標(biāo)準(zhǔn)了),它主要為了解決下面兩個(gè)問(wèn)題:

· 過(guò)多的嵌套回調(diào)問(wèn)題。

· 以Promise為主的鏈?zhǔn)交卣{(diào)問(wèn)題。

前面講解過(guò)Promise,雖然Promise解決了恐怖的嵌套回調(diào)問(wèn)題,但是解決得并不徹底,過(guò)多地使用Promise會(huì)引發(fā)以then為主的復(fù)雜鏈?zhǔn)秸{(diào)用問(wèn)題,同樣會(huì)讓代碼閱讀起來(lái)不那么順暢,而async/await就是它們的救星。

async/await是兩個(gè)關(guān)鍵字,主要用于解決異步問(wèn)題,其中async關(guān)鍵字代表后面的函數(shù)中有異步操作,await關(guān)鍵字表示等待一個(gè)異步方法執(zhí)行完成。這兩個(gè)關(guān)鍵字需要結(jié)合使用。

當(dāng)函數(shù)中有異步操作時(shí),可以在聲明時(shí)在其前面加一個(gè)關(guān)鍵字async,代碼如下:

     async function myFunc() {
       //異步操作
     }

使用async聲明的函數(shù)在被調(diào)用時(shí)會(huì)將返回值轉(zhuǎn)換成一個(gè)Promise對(duì)象,因此async函數(shù)通過(guò)return返回的值會(huì)進(jìn)入Promise的resolved狀態(tài),成為then方法中回調(diào)函數(shù)的參數(shù),代碼如下:

     // myFunc()返回一個(gè)Promise對(duì)象
     async function myFunc() {
       return 'hello';
     }
     // 使用then方法就可以接收到返回值
     myFunc().then(value => {
       console.log(value); // hello
     })

如果不想使用Promise的方式接收myFunc()的返回值,可以使用await關(guān)鍵字更加簡(jiǎn)潔地獲取返回值,代碼如下:

     async function myFunc() {
       return 'hello';
     }
     let foo = await myFunc(); // hello

await表示等待一個(gè)Promise返回,但是await后面的Promise對(duì)象不會(huì)總是返回resolved狀態(tài),如果發(fā)生異常,則進(jìn)入rejected狀態(tài),那么整個(gè)async異步函數(shù)就會(huì)中斷執(zhí)行,為了記錄錯(cuò)誤的位置和編寫(xiě)異常邏輯的代碼,需要使用try/catch,代碼如下:

     try {
       let foo = await myFunc(); // hello
     }catch(e){
       // 錯(cuò)誤邏輯
       console.log(e)
     }

下面舉一個(gè)例子,在后面的實(shí)戰(zhàn)項(xiàng)目開(kāi)發(fā)中,經(jīng)常會(huì)用到數(shù)據(jù)接口請(qǐng)求數(shù)據(jù),接口請(qǐng)求一般是異步操作,例如在Vue的mounted方法中請(qǐng)求數(shù)據(jù),代碼如下:

     async mounted () {
         // 代碼編寫(xiě)自上而下,一行一行,以便于閱讀
       let resp = await ajax.get('weibo/list')
       let top = resp[0]
       console.log(top)
     }

在上面的代碼中,ajax.get()方法會(huì)返回一個(gè)Promise,采用await進(jìn)行了接收,并且await必須包含在一個(gè)用async聲明的函數(shù)中。

可以看出,在使用了async/await之后,整個(gè)代碼的邏輯更加清晰,沒(méi)有了復(fù)雜的回調(diào)和煩瑣的換行。

至此,對(duì)于實(shí)戰(zhàn)項(xiàng)目中用到的相關(guān)ES 6語(yǔ)法基本講解完畢,如果讀者想進(jìn)一步了解ES 6的更多語(yǔ)法知識(shí),可以自行在其官網(wǎng)上學(xué)習(xí)。

主站蜘蛛池模板: 临汾市| 轮台县| 昌黎县| 化隆| 平乐县| 无为县| 岐山县| 保康县| 玛纳斯县| 莱阳市| 射洪县| 乌兰县| 邢台市| 泰宁县| 雅江县| 海南省| 措勤县| 芷江| 巴林左旗| 肥西县| 江山市| 乌拉特前旗| 思南县| 文昌市| 义马市| 万安县| 菏泽市| 绥芬河市| 遂昌县| 汽车| 温州市| 阿克| 科尔| 页游| 保亭| 江口县| 汉寿县| 明水县| 英超| 丰原市| 兴业县|