/**
* 1、注意promise的三个状态
* 2、注意绑定对象,用bind
* 3、抛出错误的时候打印错误
* 4、注意报错的报错的时候,要处理报错的信息,不能直接报错,要自己报错
* 5、promise.then的部分若不是函数,则不执行
* 6、异步执行
* 7、then函数执行的时候没有pending的状态条件
* 8、链式功能
*/
// 实现链式调用
const handlePromise = (result,newPromise,resolve,reject) => {
if ((typeof result === 'object' && typeof result !== null) || typeof result === 'function'){
const then = result.then;
if (typeof then === 'function'){
then.call(
result,
// 这里是链式调用的核心
(r) => {handlePromise(r,newPromise,resolve,reject)},
(e) => {reject(e)}
)
}else {
resolve(result)
}
}else {
resolve(result)
}
}
class Commitment{
static PENDING = '待定';
static FULFILLED = '成功';
static REJECTED = '拒绝';
// promise传入的是一个函数,并且可以执行
constructor(func) {
this.state = Commitment.PENDING;
this.result = null;
// 待定条件的时候,需要让函数先进入数组待定执行
this.resolveCallbacks = [];
this.rejectCallbacks = [];
// 这里需要注意报错,要catch报错信息,传入reject方法
try{
// 这里需要绑定this,不然在执行resolve 和 reject的时候this会跟丢
func(this.resolve.bind(this),this.reject.bind(this));
}catch (error){
this.reject(error)
}
}
// resolve 和 reject也是函数,也需要执行
resolve(result) {
setTimeout(()=>{
if (this.state === Commitment.PENDING){
this.state = Commitment.FULFILLED;
this.result = result;
this.resolveCallbacks.forEach(callback => {
callback(result)
})
}
})
}
reject(result) {
setTimeout(()=>{
if (this.state === Commitment.PENDING){
this.state = Commitment.REJECTED;
this.result = result;
this.rejectCallbacks.forEach(callback => {
callback(result)
})
}
})
}
then(onFULFILLED, onREJECTED) {
// 解决传出的参数不是函数的问题
onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => {};
onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : () => {};
let newPromise = new Commitment((resolve,reject)=>{
if (this.state === Commitment.PENDING) {
this.resolveCallbacks.push(()=> {
const res = onFULFILLED(this.result)
handlePromise(res,newPromise,resolve,reject)
})
this.rejectCallbacks.push(()=> {
const res = onREJECTED(this.result)
handlePromise(res,newPromise,resolve,reject)
})
}
if (this.state === Commitment.FULFILLED){
setTimeout(()=>{
const res = onFULFILLED(this.result);
handlePromise(res,newPromise,resolve,reject)
})
}
if (this.state === Commitment.REJECTED){
setTimeout(()=>{
const res = onREJECTED(this.result)
handlePromise(res,newPromise,resolve,reject)
})
}
})
return newPromise
}
}