實用主義:Promise讓異步回調(diào)更加優(yōu)雅

前言

函數(shù)作為一等對象,使得javascript這種弱類型,單線程腳本語言的異步方法極為方便,只需要一個callback,編譯器就能按照我們的想法執(zhí)行命令。如果只有一個簡單的異步操作,我們可以稍費腦子理清執(zhí)行順序,但是如果有多個異步方法,呃,我們就可能掉進了回調(diào)陷阱,事情遠遠沒有我們想到的那么簡單,并且我們甚至還沒考慮過異步中拋出的錯誤。

還好Promise的出現(xiàn),解救了我們,這篇文章不是講解Promise的詳細使用方法,只是通過兩個例子,看看Promise的優(yōu)雅之處,詳細資料請參考阮一峰老師 《ES6標準入門》

傳統(tǒng)的ajax回調(diào)

代碼運行于最新的Chrome版本中,Chrome目前已支持除 模塊 以外的大部分ES6方法

let xhr = new XMLHttpRequest();
    let url = 'http://chat.hstar.org:8601/rkyNA2Yvl/promise';
    xhr.responseType = "text";
    xhr.open('get', url, true);
    xhr.onreadystatechange = ((data) => {
        if (xhr.readyState===4 && xhr.status===200) {
                let data = JSON.parse(xhr,responseText);
                console.log(data.word);
        }
    });
    xhr.send(null);

結(jié)果

這是一個傳統(tǒng)的ajax回調(diào),我們把所有事務(wù)邏輯封裝在onreadystatechange事件中,并且xhr的生成與使用都在一塊代碼內(nèi)。后期的維護、DOM操作都只能該事件中進行,這只是一個異步事件,如果是多個異步事件,并且需要所有事件都能完成才能操作。Oh my god。我們可能已經(jīng)進入回調(diào)地獄。這團代碼在后期debug時候足以讓我們抓狂。

Promise的出現(xiàn)

我們再來看看一段經(jīng)過Promise封裝的代碼

function getPromise(url) {
        let p = new Promise((resolve,reject) => {
          let xhr = new XMLHttpRequest;
          xhr.open('get', url, true);
          xhr.onreadystatechange = () => {
            if (xhr.status == 200 && xhr.readyState===4 ){
                resolve(xhr.responseText);
                }   
            };
            xhr.onerr = function () {
                    reject();
            }
            xhr.send(null);
        });
        return p;
}

首先封裝一個Promise對象,我們把響應(yīng)事件封裝在resolve方法中,如果僅僅是這樣,那么和普通封裝沒有區(qū)別,我們接著來看看Promise的優(yōu)雅之處

let promise = getPromise('http://chat.hstar.org:8601/rkyNA2Yvl/promise');
    promise.
    then(data => {
        data = JSON.parse(data);
        return data;
    }).then(data => {
        document.write(data.word);
        console.log(data);
    }).catch(err => {
        console.log(err);
    });
結(jié)果

我們通過then(resolve方法的別名),進行回調(diào)操作,then方法返回的也是一個Promise對象,因此可以鏈式調(diào)用,這樣我們可以按步驟操作返回的數(shù)據(jù)。并且catch方法會捕捉每一個異步方法中的錯誤,所有的錯誤都會冒泡到這里,如果catch方法出現(xiàn)了錯誤怎么辦?別擔心done()方法會處理最后的錯誤。
通過這樣的鏈式調(diào)用,使得 關(guān)注點 分離,return的形式也更符合人腦的思考邏輯。
前面還提到了多個異步操作,我們同樣可以使用Promise.all和Promise.race方法。

最后

相比傳統(tǒng)的ajax方法,Promise的優(yōu)雅之處在于

  1. 關(guān)注點分離,每一次調(diào)用只需要完成一個任務(wù);
  2. 更符合人腦思考邏輯;
  3. 良好的錯誤處理邏輯,錯誤冒泡;
  4. all() 和 race()方法避免陷入回調(diào)地獄

這里僅僅是簡單封裝了XMLHttpRequest方法,隨著JS的發(fā)展,fetch axios vue-resource等新一代ajax方法都已經(jīng)實現(xiàn)了對Promise的封裝,這里也該大家分享一段我們項目對Promise的深度封裝實現(xiàn)(基于axios)

基于axios的封裝

所以大家也快來擁抱ES6的新特性吧
就是這樣:)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容