Promise原理分析及源碼實現(xiàn)

為什么用Promise?

  1. Promise能解決回調(diào)地獄問題
  2. Promise能多個異步操作并行,獲取最終結果

Promise三種狀態(tài)

  • Pending Promise對象實例創(chuàng)建時候的初始狀態(tài)
  • Fulfilled 可以理解為成功的狀態(tài)
  • Rejected 可以理解為失敗的狀態(tài)

Promise狀態(tài)轉(zhuǎn)換

image

Promise一旦從pending狀態(tài)到resolve狀態(tài)或者reject狀態(tài)就不會再改變,能保證結果的正確性,不會出現(xiàn)從成功到失敗或者從失敗到成功的情況。

原生Promise使用分析

let promise = new Promise((resolve,reject)=>{
    resolve("xxx")
    reject("sssss")
  })
  
  promise.then(res=>{
    console.log("success",res);
  },e=>{
    console.log("fail",e);
  })

Promise

Promise

創(chuàng)建一個Promise需要傳遞一個executor回調(diào)函數(shù)作為參數(shù),來初始化Promise。executor中有兩個參數(shù),一個resolve用來回調(diào)返回值或者另一個Promise,一個reject用來回調(diào)失敗值或者Error。

then()

then函數(shù)

then函數(shù)需傳遞兩個函數(shù)作為參數(shù),一個回調(diào)resolve的結果,一個回調(diào)reject的結果

const STATUS = {
    "PENDING": "pending",
    "FULFILLED": "fulfilled",
    "REJECTED": "rejected"
}


class Promise {

    /**
     *  Creates a new Promise.
     *
     *  @param executor — A callback used to initialize the promise. 
     *  This callback is passed two arguments: a resolve callback used to resolve the promise
     *  with a value or the result of another promise, and a reject callback used to reject the 
     *  promise with a provided reason or error.
     */
    constructor(executor) {
        this.status = STATUS.PENDING;
        this.value = undefined;
        this.reason = undefined;

        const resolve = (value) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.FULFILLED;
                this.value = value;
            }
        };

        const reject = (reason) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.REJECTED;
                this.reason = reason;
            }
        };

        try {
            executor(resolve, reject);
        } catch (error) {

        }
    }
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onfulfilled — The callback to execute when the Promise is resolved.
     * @param onrejected — The callback to execute when the Promise is rejected.
     * @returns — A Promise for the completion of which ever callback is executed. 
     */
    then(onfulfilled,onrejected) {
        if(this.status === STATUS.FULFILLED){
            onfulfilled(this.value)
        }
        if(this.status === STATUS.REJECTED){
            onrejected(this.reason)
        }
    }
}

module.exports = Promise;
let promise = new Promise((resolve,reject)=>{
    resolve("xxx")
    reject("sssss")
  })
  
  promise.then(res=>{
    console.log("success",res);
  },e=>{
    console.log("fail",e);
  })

//success xxx

現(xiàn)在我們實現(xiàn)了一個簡單的Promise,可以在Promise中通過resolve函數(shù)傳遞普通值到then函數(shù)中,并在then的onfullfilled中取出,或者通過reject傳遞在onrejected中取出。并且實現(xiàn)Promise狀態(tài)從pendding到resolve或reject,不可逆。

實現(xiàn)鏈式調(diào)用

then(onfulfilled,onrejected) {
        let promise2 = new Promise((resolve,reject)=>{
            if(this.status === STATUS.FULFILLED){
                let x = onfulfilled(this.value)
                resolve(x)
            }
            if(this.status === STATUS.REJECTED){
                let x = onrejected(this.reason)
                reject(x)
            } 
            if(this.status === STATUS.PENDING){
                this.onResolvedCallbacks.push(()=>{
                    onfulfilled(this.value);
                });
                this.onrejectedCallbacks.push(()=>{
                    onrejected(this.reason);
                });
            }
        });
        return promise2;
        
    }
    
const resolve = (value) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach(fn=>fn());
            }
        };
const reject = (reason) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.REJECTED;
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn=>fn());
            }
        };
        
let promise = new Promise((resolve,reject)=>{
    resolve("xxx")
    reject("sssss")
  })
  
  promise.then(res=>{
    console.log("success",res);
    return "next"
  },e=>{
    console.log("fail",e);
  }).then(res=>{
    console.log("success1",res)
  })
  //success xxx
  //success1 next

處理返回值是Promise的情況 resolvePromise函數(shù)的實現(xiàn)

//解析x類型,決定promise2走成功還是失敗
function resolvePromise(promise2, x, resolve, reject) {
    console.log("x", x)
    if (x === promise2) {
        return reject(new TypeError("返回值錯誤,不能使用同一個promise"))
    }
    //只有object或者function才能是Promise
    if ((typeof x === 'object' && typeof x != null) || typeof x === 'function') {
        let called = false;//成功或者失敗方法只能調(diào)用一次,防止其他Promise實現(xiàn)錯誤
        try {
            let then = x.then;//通過判斷x上是否有then函數(shù),判斷x是否是一個Promise
            if (typeof then === 'function') {
                then.call(x, y => {
                    if (called) return;
                    called = true;
                    // resolve(y) y有可能還是promise 遞歸解析 直到是普通值為止
                    resolvePromise(promise2, y, resolve, reject);
                }, r => {
                    if (called) return;
                    called = true;
                    reject(r);
                })
            } else {
                reject(x);
            }
        } catch (error) {
            if (called) return;
            called = true;
            reject(error);
        }

    } else {
        reject(x);
    }
}

引入Promise A+ 單元測試

Promise.deferred = function () {
    let dfd = {};
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd;
}

npm install promises-aplus-tests
promises-aplus-tests myPromise.js
單元測試

如果單元測試通過,證明我們的Promise符合Promise A+規(guī)范

完整代碼

const STATUS = {
    "PENDING": "pending",
    "FULFILLED": "fulfilled",
    "REJECTED": "rejected"
}
//解析x類型,決定promise2走成功還是失敗
function resolvePromise(promise2, x, resolve, reject) {
    if (x == promise2) {
        return reject(new TypeError("返回值錯誤,不能使用同一個promise"))
    }
    //只有object或者function才能是Promise
    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
        let called = false;//成功或者失敗方法只能調(diào)用一次,防止其他Promise實現(xiàn)錯誤
        try {
            let then = x.then;//通過判斷x上是否有then函數(shù),判斷x是否是一個Promise
            if (typeof then === 'function') {
                then.call(x, y => {
                    if (called) return;
                    called = true;
                    // resolve(y) y有可能還是promise 遞歸解析 直到是普通值為止
                    resolvePromise(promise2, y, resolve, reject);
                }, r => {
                    if (called) return;
                    called = true;
                    reject(r);
                })
            } else {
                resolve(x);
            }
        } catch (error) {
            if (called) return;
            called = true;
            reject(error);
        }

    } else {
        resolve(x);
    }
}

class Promise {

    /**
     *  Creates a new Promise.
     *
     *  @param executor — A callback used to initialize the promise. 
     *  This callback is passed two arguments: a resolve callback used to resolve the promise
     *  with a value or the result of another promise, and a reject callback used to reject the 
     *  promise with a provided reason or error.
     */
    constructor(executor) {
        this.status = STATUS.PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        const resolve = (value) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };

        const reject = (reason) => {
            if (this.status === STATUS.PENDING) {
                this.status = STATUS.REJECTED;
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        };

        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error)
        }
    }
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onfulfilled — The callback to execute when the Promise is resolved.
     * @param onrejected — The callback to execute when the Promise is rejected.
     * @returns — A Promise for the completion of which ever callback is executed. 
     */
    then(onfulfilled, onrejected) {
        //判斷then傳遞的參數(shù)是否是函數(shù),如果不是則包裝成一個函數(shù)
        onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : x => x;
        onrejected = typeof onrejected === 'function' ? onrejected : error => {
            throw error
        };
        let promise2 = new Promise((resolve, reject) => {
            if (this.status === STATUS.FULFILLED) {
                setTimeout(() => { //創(chuàng)建一個宏任務,保證promise2已完成創(chuàng)建
                    try {
                        let x = onfulfilled(this.value); //x的返回值有可能是一個新的Promise,需要進行判斷和處理
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error) //如果返回異常,捕獲并作為失敗結果返回
                    }
                    // resolve(x)
                }, 0);

            }
            if (this.status === STATUS.REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onrejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error)
                    }
                    // reject(x)
                }, 0);
            }

            if (this.status === STATUS.PENDING) {
                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onfulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)

                });
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onrejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0);
                });
            }
        });
        return promise2;

    }
    catch(errFn) {
        return this.then(null, errFn);
    }
}

Promise.deferred = function () {
    let dfd = {};
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    })
    return dfd;
}
module.exports = Promise;
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容