1. 程式人生 > >promise加箭頭函式處理非同步結果

promise加箭頭函式處理非同步結果

Promise物件

es6中新增了promise物件,為了處理非同步訊息而生,在此之前處理非同步拿到的資料就是回撥巢狀回撥,有了Promise我們就可以在需要使用非同步處理結果的地方呼叫Promise.then(func)

Promise定義

摘自 阮一峰 ECMAScript 6 入門

所謂Promise,簡單說就是一個容器,裡面儲存著某個未來才會結束的事件(通常是一個非同步操作)的結果。

在js中很經典的非同步就是ajax請求了,我在第一個專案當中用到ajax原生請求,處理ajax請求的結果全在回撥函式當中進行,判斷狀態碼,作出相應的處理,在不同的狀態碼下的處理又非常的多,然後就是一層層巢狀,還蠻爽的==

function getMessage(url,data) {  
var request = new XMLHttpRequest();
request.open("POST", url);    
request.responseType = "json";    
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');    
request.send(data); 
request.onload = function () {
        if (this.status === 200
) { if (this.response.code === 200) { this.response.data.forEach(function (obj) { //此處處理拿到的資料 }) } else //此處處理後端返回錯誤 } else //此處處理網路請求錯誤
}; }

基本上整個模組的操作都在回撥裡面做了,因為請求的結果資料就在那裡,非同步的結果是不確定的,只能在回撥函式做各種各樣的處理。

Promise的三種狀態

一個 Promise有以下幾種狀態:

  • pending: 初始狀態,不是成功或失敗狀態。
  • fulfilled: 意味著操作成功完成。
  • rejected: 意味著操作失敗。

描述:
Promise 物件是一個代理物件(代理一個值),被代理的值在Promise物件建立時可能是未知的。它允許你為非同步操作的成功和失敗分別繫結相應的處理方法(handlers )。 這讓非同步方法可以像同步方法那樣返回值,但並不是立即返回最終執行結果,而是一個能代表未來出現的結果的promise物件。

我們給出一個用promise物件封裝的一個ajax請求:

 function getDate(url, data) {
     return new Promise(function(resolve, reject) {
         var request = new XMLHttpRequest(); 
         request.open("POST", url);
         request.responseType = "json"; 
         request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');                    
         request.send(data);                 
         request.onload = function() {                    
             if (this.status === 200) {
                 resolve(this.response);
             } else {    
                 reject(this.status);
             }
         }
    })
}

// 在需要處理資料的地方
getDate(url, data).then(function(response) {
    /此處處理拿到的資料 
}).catch(function(err){
    //此處處理錯誤
})

上面的示例就是用Promise物件封裝了ajax請求,解決了在回撥裡面處理所有結果的尷尬。

axios請求

我們可以不用人工封裝,而是藉助已經封裝好的模組axios去請求,原理看著都一樣,甚至用起來和我們自己封裝的都一樣

function getDate(url, data) {
    axios.defaults.baseURL = url;  
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 
    //此處放了一個get請求,就沒用到data
     axios.get('/articles/articleList').then(function(response) {
         if(response.status == 200) {
             if(response.data.code == 200) {
                  //處理
              } else {
                  //此處處理後端返回狀態錯誤
              }
        }
    }).catch(function(err) {
        //此處處理請求錯誤
    });
}

這裡我要隆重的說一句,不管這個Promise對非同步的結果做了什麼,非同步還是非同步,你想把非同步執行的結果傳出來還是不可能,除非用generator或者async轉成同步,顯然把他轉成同步不合算。
接下來我們就用箭頭函式加promise的方法解決結果不能傳出去的問題。

箭頭函式

ES6大法的箭頭函式,說一點:箭頭函式的this。
箭頭函式的this是繫結外部環境的,咱們直接看例子

var name = "zhangchi";
var Obj = {
    name: "chichi",
    fun1: function(){
        console.log(this.name);
    },
    fun2: () => {
        console.log(this.name);
    }
}

Obj.fun1(); // chichi
Obj.fun2(); //zhangchi

看完這個例子大致就知道,箭頭函式和普通函式的this指向是不同的,所以不要在一個類裡面用箭頭函式。

終極解決方案

var data = {}; //接收非同步返回的結果
function getDate(url, data) {
    axios.defaults.baseURL = url;  
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 
     axios.get('/articles/articleList').then((response) => {
         if(response.status == 200) {
             if(response.data.code == 200) {
                  this.data = response.data.data;
              } else {
                  //此處處理後端返回狀態錯誤
              }
        }
    }).catch(function(err) {
        //此處處理請求錯誤
    });
}