談談Promise的前世此生

前言

談到Promise,你們都熟爛於心,有的童鞋已經在項目中大規模使用async/await,甚至有的開始用上了fetch。不管什麼方式,實質都是Promise的封裝和語法糖,因此弄清楚了Promise的前因後果,有助於更好地理解和使用Promise。javascript

歷史演變

  • callback
  • observers
  • JSDeferred
  • jQuery Deferred
  • Promise(*)
  • generator
  • async/await
  • fetch

callback

網上曾流傳一張這樣的圖(如上圖所示)來形容(callback hell)回調地獄,能夠說很生動形象了。代碼規範作得好一點的童鞋可能會把回調函數拆開,但若是不謹慎,一不當心就會寫出這樣的代碼來。在刀耕火種年代,回調是最爲快捷有效的辦法。其思想是把要執行的代碼做爲函數參數傳遞,而後在異步代碼執行完執行傳入的回調函數。

const fetchApi = (callback) => {
    setTimeout(() => {
        //todo something...
        callback && calback();
    }, 1000);
};

fetachApi(() => {
    //some code...
});
複製代碼

這樣雖然能夠解決問題,可是還存在如下幾個問題:前端

  • 代碼易讀性差
  • 代碼不緊湊
  • 依然會有callback hell問題

observers

觀察者模式,jQuery三行代碼搞定發佈訂閱模式java

//訂閱
$.on(document, function() {
    
});
//取消訂閱
$.off(document, function() {
    
});
//發佈
$.trigger(document, function() {
    
});
複製代碼

listeners

EventEmitter

const EventEmitter = require('Event.EventEmitter');
const eventEmitter = new EventEmitter();
eventEmitter.on('data', () => {
    //some code...
});
eventEmitter.emit();
複製代碼

DOM事件

document.onclick = function() {
    //some code...
}
複製代碼

jQuery事件綁定

$(document).on('click', function() {
    //some code...
})
複製代碼

JSDeferred

Promise里程碑,在Promise還沒造成規範以前,各大庫(mochikit,dojo,jQuery...)百花齊放,都實現了各自的Promise模型。ajax

jQuery Deferred

Promise先驅者,前端新人可能對jQuery比較熟悉,在平時的工做中,據我所知,我身邊的前端童鞋幾乎都不知道這個jQuery的這個api。其實早在Promise誕生前,jQuery內部已經實現Promise相似功能,只是沒有成爲規範被歸入。json

$.Deferred
$.when()
複製代碼

Promise

這個是本文講述的重點api

const promise = new Promise((resolve, reject) => {
    if (data) {
        resolve(data);
    }else {
        reject(error);
    }
});
promise.then(data => {
   //some code... 
});
Promise.all([fetchApi1, fetchApi2]);
Promise.trace([fetchApi1, fetchApi2]);
複製代碼

generator

迭代器模式, async/await過渡產品promise

const loginHandler = *() => {
    yield fetchApi();
}
loginHandler.next();
複製代碼

async/await

像寫同步代碼同樣書寫異步代碼bash

const loginHandler = async () => {
    const data = await fetchApi();
    //do something with data...
};
複製代碼

fetch

將來的ajax異步

fetach(apiUrl, data => data.json() => data )
.then(data => {
    //some code...
});
複製代碼
相關文章
相關標籤/搜索