手寫一個簡易版的Promise

1、瞭解Promise

Promise 是異步編程的一種解決方案,ES6新增的一個對象,用來傳遞異步操做的消息。它表明了某個將來纔會知道結果的事件(一般是一個異步操做),而且這個事件提供統一的 API,可供進一步處理。編程

Promise有如下兩個特色:數組

(1)Promise 的狀態不受外界影響。Promise 翻譯過來是承諾的意思,這個承諾會在將來有一個確切的答覆,而且該承諾有三種狀態,分別是:等待中pending、已完成 resolved、已失敗rejected。它表明一個異步操做,只有異步操做的結果能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。緩存

(2)Promise一旦由等待狀態變成爲其餘狀態就永遠不能更改成其餘狀態了。也就是說,當狀態從 Pending 變爲 Resolved 或者 Rejected 後,狀態就不能更改了。框架

new Promise((resolve, reject) => {
    resolve('resolve')
    reject('reject') // 這個reject無效
})
複製代碼

當咱們在構造 Promise 的時候,構造函數內部的代碼是當即執行的:異步

new Promise((resolve, reject) => {
    console.log(1);
    resolve('resolve')
})
console.log(2);
複製代碼

Promise 的鏈式調用:異步編程

new Promise(function(resolve, reject){
    resolve(1);
}).then(function(data){
    console.log(data);
    return new Promise(function(resolve, reject){
        resolve(2);
    })
}).then(function(data){
    console.log(data);
}).catch(function(err){
    console.log(err);
})
複製代碼

Promise 很好地解決了回調地獄的問題,使代碼能夠變得更加簡潔優雅。函數

Promise 也存在一些缺點:(1) 它一旦新建就會當即執行,沒法中途取消;(2) 錯誤是須要經過回調函數捕獲。ui

2、手寫一個簡易版的Promise

首先,建立三個表示狀態的常量:this

const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
複製代碼

搭建構造函數的框架:spa

function myPromise(fn) { // 傳入的是一個函數
    // 定義一個常量that來緩存當前的this對象
    const that = this;
    // 初始狀態是pending
    that.status = PENDING;
    // 定義一個變量來保存resolve或者reject傳入的值
    that.param = null;
    // 定義兩個數組來記錄異步操做以後回來執行的函數(即保存then中的回調函數,等狀態改變時執行)
    that.resolvedCallBacks = []; // 狀態轉爲成功以後執行的函數
    that.rejectedCallBacks = []; // 狀態轉爲失敗以後執行的函數
    // 定義resolve函數
    function resolve() {

    }
    // 定義reject函數
    function reject() {
        
    }
    // 執行fn函數
    fn();
}
複製代碼

下面來完善resolvereject函數:

// 定義resolve函數
    function resolve(param) {
        // 只有狀態爲初始狀態時才執行
        if (that.status === PENDING) {
            that.status = RESOLVED; // 執行以後狀態改成成功
            that.param = param; // 記錄傳入的參數
            // 遍歷回調函數並執行
            that.resolvedCallBacks.map(function(callback){
                callback && callback(that.param);
            })
        }
    }
    // 定義reject函數
    function reject(param) {
        // 只有狀態爲初始狀態時才執行
        if (that.status === PENDING) {
            that.status = REJECTED; // 執行以後狀態改成失敗
            that.param = param; // 記錄傳入的參數
            // 遍歷回調函數並執行
            that.resolvedCallBacks.map(function(callback){
                callback && callback(that.param);
            })
        }
    }
複製代碼

執行 fn 函數時,把 resolvereject 當作參數傳入,捕捉到錯誤後執行 reject 函數

// 執行fn函數
    try {
        fn(resolve, reject);
    } catch(e) {
        reject(e);
    }
複製代碼

接下來實現 then 函數:

// then函數有兩個參數onFulfilled, onRejected(參數爲函數)
// 當前實例狀態變成成功狀態時,onFulfilled做爲回調函數被調用
// 當前實例狀態變成失敗狀態時,onRejected做爲回調函數被調用
myPromise.prototype.then = function(onFulfilled, onRejected) {
    const that = this;
    // 當狀態爲初始狀態時,把對應函數保存到對應回調函數數組中
    if (that.status === PENDING) {
        that.resolvedCallBacks.push(onFulfilled);
        that.rejectedCallBacks.push(onRejected);
    }
    // 當狀態爲成功狀態時,執行onFulfilled
    if (that.status === RESOLVED) {
        onFulfilled(that.param);
    }
    // 當狀態爲成功狀態時,執行onFulfilled
    if (that.status === REJECTED) {
        onRejected(that.param);
    }
}
複製代碼

以上就是簡易版的 Promise 實現了,最後來簡單的運行一下:

new myPromise(function(resolve, reject){
    resolve(1);
    // reject(2);
}).then(function(data) {
    console.log(data);
}, function(err) {
    console.log(err);
})
複製代碼
相關文章
相關標籤/搜索