手写Promise

125 阅读2分钟

实现一个最简单的promise例子

  • 从使用层面分析,使用promise时,需要实例化Promise构造函数
  • Promise有三种状态,pendding,resolved,rejected
  • 构造函数立即执行

通过此三条分析,可以写出一个最简单的例子

class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
    }
    then(successCallback, failCallback) {
        successCallback(this.value)
    }
}
let p = new myPromise((resolve, reject) => {
    resolve('成功')
})
p.then(res => {
    console.log(res);
}, res => {
    console.log(res);
});
  • 通过结果可知,可以正常得到resolve中传入的值。
  • 但是如果resolve异步执行,就拿不到值了,案例代码如下
class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
    }
    then(successCallback, failCallback) {
        successCallback(this.value)
    }
}
let p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    })
})
p.then(res => {
    console.log(res); // 成功
}, res => {
    console.log(res);
});
  • 针对异步情况的优化
  • resolve异步执行,执行then函数时,status的状态为pendding,还没有执行resolve方法,所以需要一个数组来存储函数,当value没有值时,把函数存到栈中。
  • 代码如下
class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    successCallbackList = []
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
        if (this.successCallbackList.length > 0) {
            this.successCallbackList.shift()(value);
        }
    }
    then(successCallback, failCallback) {
        if(!this.value) {
            this.successCallbackList.push(successCallback)
        } else {
            successCallback(this.value)
        }
        
    }
}
let p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    })
})
p.then(res => {
    console.log(res); // 成功
}, res => {
    console.log(res);
});
  • 如果then执行多次就拿不到值了,代码如下
class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    successCallbackList = []
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
        if (this.successCallbackList.length > 0) {
            this.successCallbackList.shift()(value);
        }
    }
    then(successCallback, failCallback) {
        if(!this.value) {
            this.successCallbackList.push(successCallback)
        } else {
            successCallback(this.value)
        }
    }
}
let p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    })
})
p.then(res => {
    console.log(res); // 成功
}, res => {
    console.log(res);
});
p.then(res => {
    console.log(res); // 不执行
}, res => {
    console.log(res);
});
  • 需要针对传入successCallbackList的函数依次出栈,代码如下
class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    successCallbackList = []
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
        while (this.successCallbackList.length) {
            this.successCallbackList.shift()(value);
        }
    }
    then(successCallback, failCallback) {
        if(!this.value) {
            this.successCallbackList.push(successCallback)
        } else {
            successCallback(this.value)
        }
    }
}
let p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    })
});
p.then(res => {
    console.log(res); // 成功
}, res => {
    console.log(res);
});
p.then(res => {
    console.log(res); // 成功
}, res => {
    console.log(res);
});
  • 在使用promise时,then支持链式调用,所以在then函数中,要返回一个新的promise
  • 还需要判断在then中返回的是常量还是一个promise
class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    successCallbackList = []
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
        while (this.successCallbackList.length) {
            this.successCallbackList.shift()(value);
        }
    }
    then(successCallback, failCallback) {
        let promiseResolve = new myPromise((resolve, reject) => {
            if (this.status === 'resolved') {
                let result = successCallback(this.value);
                this.resolvePromise(result, resolve, reject);
            } else {
                this.successCallbackList.push(successCallback)
            }
        });
        return promiseResolve;
    }
    resolvePromise(result, resolve, reject) {
        if (result instanceof myPromise) {
            result.then(resolve, reject)
        } else {
            resolve(result)
        }
    }
}
let p = new myPromise((resolve, reject) => {
     resolve('成功');
});
p.then(res => {
    console.log(res); // 成功
    return '链式调用';
}, res => {
    console.log(res);
}).then(res=>{
    console.log(res); // 链式调用
})

  • 针对resolve异步时,还需要特殊处理
class myPromise {
    constructor(exector) {
        exector(this.resolve, this.reject);
    }
    value = undefined
    status = 'pendding'
    successCallbackList = []
    resolve = (value) => {
        if (this.status !== 'pendding') return
        this.value = value;
        this.status = 'resolved'
        while (this.successCallbackList.length) {
            this.successCallbackList.shift()(value);
        }
    }
    then(successCallback, failCallback) {
        let promiseResolve = new myPromise((resolve, reject) => {
            if (this.status === 'resolved') {
                let result = successCallback(this.value);
                this.resolvePromise(result, resolve, reject);
            } else {
                this.successCallbackList.push(()=>{
                    let result = successCallback(this.value);
                    this.resolvePromise(result, resolve, reject);
                })
            }
        });
        return promiseResolve;
    }
    resolvePromise(result, resolve, reject) {
        if (result instanceof myPromise) {
            result.then(resolve, reject)
        } else {
            resolve(result)
        }
    }
}
let p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    })
});
p.then(res => {
    console.log(res); // 成功
    return '链式调用';
}, res => {
    console.log(res);
}).then(res=>{
    console.log(res); // 链式调用
})
  • 除此之外,还需要补充异常时的调用以及兼容性处理
  1. then的