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

1.5.3 Promise和async/await

1.Promise

Promise是一種適用于異步操作的機制,比傳統的回調函數解決方案更合理和更強大。從語法上說,Promise是一個對象,從它可以獲取異步操作的結果:成功或失敗。在Promise中,有三種狀態:pending(進行中)、resolved(已成功)和rejected(已失敗)。只有異步操作的結果可以決定當前是哪一種狀態,無法被Promise之外的方式改變。這也是Promise這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。創建一個Promise對象,代碼如下:

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

在上面的代碼中,創建了一個Promise對象,Promise構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve和reject。這是兩個內置函數,resolve函數的作用是將Promise對象的狀態變為“成功”,在異步操作成功時調用,并將異步操作的結果作為參數傳遞出去;reject函數的作用是將Promise對象的狀態變為“失敗”,在異步操作失敗時調用,并將異步操作報出的錯誤作為參數傳遞出去。當代碼中出現錯誤(Error)時,就會調用catch回調方法,并將錯誤信息作為參數傳遞出去。

Promise對象實例生成后,可以用then方法分別指定resolved(成功)狀態和rejected(失敗)狀態的回調函數以及catch方法,比如:

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

then()方法返回的是一個新的Promise實例(不是原來那個Promise實例)。因此,可以采用鏈式寫法,即then()方法后面再調用另一個then()方法,比如:

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

下面是一個用Promise對象實現的Ajax操作get方法的例子。

     var getJSON = function(url) {
       // 返回一個Promise對象
       var promise = new Promise(function(resolve, reject){
         var client = new XMLHttpRequest(); //創建XMLHttpRequest對象
         client.open("GET", url);
         client.onreadystatechange = onreadystatechange;
         client.responseType = "json";              //設置返回格式為json
         client.setRequestHeader("Accept", "application/json");//設置發送格式為json
         client.send();//發送
         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的基本知識可以便于后續學習使用服務端渲染。當然,Promise的應用場合還是比較多的,如果想要深入了解,可以訪問網址:https://developer.mozilla.org/en-US/docs/Web/Java Script/Reference/Global_Objects/Promise,進行系統的學習。

2.async/await

async/await語法在2016年就已經提出來了,屬于ES 7中的一個測試標準(目前來看是直接跳過ES 7,列為ES 8的標準了),它主要為了解決下面兩個問題:

· 過多的嵌套回調問題。

· 以Promise為主的鏈式回調問題。

前面講解過Promise,雖然Promise解決了恐怖的嵌套回調問題,但是解決得并不徹底,過多地使用Promise會引發以then為主的復雜鏈式調用問題,同樣會讓代碼閱讀起來不那么順暢,而async/await就是它們的救星。

async/await是兩個關鍵字,主要用于解決異步問題,其中async關鍵字代表后面的函數中有異步操作,await關鍵字表示等待一個異步方法執行完成。這兩個關鍵字需要結合使用。

當函數中有異步操作時,可以在聲明時在其前面加一個關鍵字async,代碼如下:

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

使用async聲明的函數在被調用時會將返回值轉換成一個Promise對象,因此async函數通過return返回的值會進入Promise的resolved狀態,成為then方法中回調函數的參數,代碼如下:

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

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

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

await表示等待一個Promise返回,但是await后面的Promise對象不會總是返回resolved狀態,如果發生異常,則進入rejected狀態,那么整個async異步函數就會中斷執行,為了記錄錯誤的位置和編寫異常邏輯的代碼,需要使用try/catch,代碼如下:

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

下面舉一個例子,在后面的實戰項目開發中,經常會用到數據接口請求數據,接口請求一般是異步操作,例如在Vue的mounted方法中請求數據,代碼如下:

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

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

可以看出,在使用了async/await之后,整個代碼的邏輯更加清晰,沒有了復雜的回調和煩瑣的換行。

至此,對于實戰項目中用到的相關ES 6語法基本講解完畢,如果讀者想進一步了解ES 6的更多語法知識,可以自行在其官網上學習。

主站蜘蛛池模板: 策勒县| 南溪县| 花莲县| 怀仁县| 乐至县| 玉环县| 镇雄县| 阿拉尔市| 玉林市| 唐山市| 龙口市| 边坝县| 镇雄县| 新宁县| 富宁县| 澄城县| 桃江县| 增城市| 凤台县| 通化市| 灯塔市| 六枝特区| 清镇市| 阿拉善右旗| 枣阳市| 乌拉特后旗| 杭锦后旗| 班戈县| 定州市| 安吉县| 托里县| 安义县| 义马市| 厦门市| 海盐县| 昌平区| 磐石市| 大渡口区| 东台市| 天镇县| 泰顺县|