Promise原理分析及源码实现

为什么用Promise?

  1. Promise能解决回调地狱问题
  2. Promise能多个异步操作并行,获取最终结果

Promise三种状态

  • Pending Promise对象实例创建时候的初始状态
  • Fulfilled 可以理解为成功的状态
  • Rejected 可以理解为失败的状态

Promise状态转换

image

Promise一旦从pending状态到resolve状态或者reject状态就不会再改变,能保证结果的正确性,不会出现从成功到失败或者从失败到成功的情况。

原生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

创建一个Promise需要传递一个executor回调函数作为参数,来初始化Promise。executor中有两个参数,一个resolve用来回调返回值或者另一个Promise,一个reject用来回调失败值或者Error。

then()

then函数

then函数需传递两个函数作为参数,一个回调resolve的结果,一个回调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

现在我们实现了一个简单的Promise,可以在Promise中通过resolve函数传递普通值到then函数中,并在then的onfullfilled中取出,或者通过reject传递在onrejected中取出。并且实现Promise状态从pendding到resolve或reject,不可逆。

实现链式调用

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函数的实现

//解析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;//成功或者失败方法只能调用一次,防止其他Promise实现错误
        try {
            let then = x.then;//通过判断x上是否有then函数,判断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+规范

完整代码

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;//成功或者失败方法只能调用一次,防止其他Promise实现错误
        try {
            let then = x.then;//通过判断x上是否有then函数,判断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传递的参数是否是函数,如果不是则包装成一个函数
        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(() => { //创建一个宏任务,保证promise2已完成创建
                    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;

你可能感兴趣的:(Promise原理分析及源码实现)