手写promise实现过程

341 阅读12分钟

原生promise用法:

new Promise((resolve, reject) => {
    resolve("done")
})

现在来自己开发一个Promise实现,提升异步编程的能力。

1 声明promise类并绑定this

class PM {
    // 使用静态属性保存状态值
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    // executor为执行者
    constructor(executor) {
        this.status = PM.PENDING;
        this.value = null;
        executor(this.resolve, this.reject)
    }

    resolve(value) {
        this.status = PM.FULFILLED;
        this.value = value
    }

    reject(reason) {
        this.status = PM.REJECTED;
        this.value = reason
    }
}

测试代码:

<script>
  let p = new PM((resolve, reject) => {
    resolve("done");
  });
  console.log(p)
</script>

测试结果:

报错原因:因为 resolve或reject方法在executor中调用,作用域也是executor作用域,这会造成this指向window,现在我们使用的是class定义,this为undefined。

修改constructor代码:

constructor(executor) {
    this.status = PM.PENDING;
    this.value = null;
    // 增加错误捕获,当执行者出现错误时触发拒绝状态
    try {
        // 绑定this值,指向当前class
        executor(this.resolve.bind(this), this.reject.bind(this))
    } catch (error) {
        this.reject(error)
    }
}
constructor(executor) {
    this.status = PM.PENDING;
    this.value = null;
    // 绑定this值,指向当前class
    executor(this.resolve.bind(this), this.reject.bind(this)) 
}

再次测试,结果:

2 实现状态保护

测试代码:

<script>
let p = new PM((resolve, reject) => {
     resolve("done")
     reject("fail")
});
console.log(p)
</script>

测试结果:

结果不符合原生promise定义,状态只能改变一次,在resolve与reject中添加判断即可:

resolve(value) {
    // 添加状态判断
    if (this.status === PM.PENDING) {
        this.status = PM.FULFILLED;
        this.value = value
    }
}

reject(reason) {
    // 添加状态判断
    if (this.status === PM.PENDING) {
        this.status = PM.REJECTED;
        this.value = reason
    }
}

3 then的基础构建与异常捕获

原生promise的then方法:

new Promise((resolve, reject) => {
    resolve("done")
    // reject("fail")
}).then(value => {
    console.log("resolve", value)
}, reason => {
    console.log("reason", reason)
})

自定义class添加基础then方法:

then(onFulfilled, onRejected) {
    // 只有状态改变后才执行then方法
    if (this.status === PM.FULFILLED) {
        onFulfilled(this.value)
    }
    if (this.status === PM.REJECTED) {
        onRejected(this.value)
    }
}

测试代码:

<script>
let p = new PM((resolve, reject) => {
  resolve("done")
  // reject("fail")
}).then(value => {
  console.log("resolve", value)
}, reason => {
  console.log("reason", reason)
})
</script>

测试结果:

现在执行以下测试代码:

<script>
let p = new PM((resolve, reject) => {
   reject("fail")
}).then(value => {
   console.log("resolve", value)
})
</script>

结果报错:

现在完善then方法来处理状态的改变:

then(onFulfilled, onRejected) {
    // then的每个方法都不是必须的,所以当没有传递时给上默认值
    if (typeof onFulfilled !== "function") {
        onFulfilled = () => { }
    }
    if (typeof onRejected !== "function") {
        onRejected = () => { }
    }
    // 当执行then传递的函数发生异常时,统一交给onRejected来处理错误
    if (this.status === PM.FULFILLED) {
        try {
            onFulfilled(this.value)
        } catch (error) {
            onRejected(error)
        }
    }
    if (this.status === PM.REJECTED) {
        try {
            onRejected(this.value)
        } catch (error) {
            onRejected(error)
        }
    }
}

4 实现then的异步操作

先执行原生promise:

new Promise((resolve, reject) => {
    resolve("原生done")
}).then(value => {
    console.log("resolve", value)
})
console.log("同步代码")

原生结果:

然后使用自定义方法,执行测试代码:

<script>
let p = new PM((resolve, reject) => {
    resolve("自定义done")
}).then(value => {
    console.log("resolve", value)
})
console.log("同步代码")
</script>

测试结果:

结果顺序不一致原因:目前的代码产生的Promise不是异步的。

修改then里面的方法:

if (this.status === PM.FULFILLED) {
    // 使用setTimeout来将onFulfilled与onRejected做为异步宏任务执行
    setTimeout(() => {
        try {
            onFulfilled(this.value)
        } catch (error) {
            onRejected(error)
        }
    })
}
if (this.status === PM.REJECTED) {
    // 异步执行
    setTimeout(() => {
        try {
            onRejected(this.value)
        } catch (error) {
            onRejected(error)
        }
    })
}

5 promise的pending状态处理

先看原生promise:

new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("原生done")
    }, 1000)
}).then(value => {
    console.log(value)
})
console.log("同步代码")

原生执行结果:先打印 "同步代码",1秒后打印 "原生done"

但目前自定义then方法无法处理pending时的状态,不会打印setTimeout里的resolve结果。因为实例化完PM对象之后,立刻就执行了then方法。但是resolve改变状态是在1秒以后。

查找并理解问题原因,在then方法里打印this值:

then(onFulfilled, onRejected) {
    // 打印this,为了查看问题
    console.log(this)
    ...
}

此时执行测试代码:

<script>
let p = new PM((resolve, reject) => {
   setTimeout(()=>{
       resolve("自定义done")
   },1000)
}).then(value => {
console.log("resolve", value)
})
</script>

测试结果:

1秒后状态变为解决:

所以如果测试代码的状态改变是异步的,但自定义class的方法还没有对此进行处理,现在修改方法:

class PM {
    ...
    constructor(executor) {
        this.status = PM.PENDING;
        this.value = null;
        // 1.在构造函数中添加callbacks来保存pending状态时处理函数,当状态改变时循环调用
        this.callbacks = [];
        try {
            executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
            this.reject(error)
        }
    }
    // 3.resovle与reject中添加处理callback方法的代码
    resolve(value) {
        if (this.status === PM.PENDING) {
            this.status = PM.FULFILLED;
            this.value = value;
            // 1秒后,状态变为解决或拒绝,从回调数组里取出函数执行
            this.callbacks.map(callback => callback.onFulfilled(value))
        }
    }

    reject(reason) {
        if (this.status === PM.PENDING) {
            this.status = PM.REJECTED;
            this.value = reason;
            // 1秒后,状态变为解决或拒绝,从回调数组里取出函数执行
            this.callbacks.map(callback => callback.onRejected(reason))
        }
    }

    then(onFulfilled, onRejected) {
        if (typeof onFulfilled !== "function") {
            onFulfilled = () => { }
        }
        if (typeof onRejected !== "function") {
            onRejected = () => { }
        }
        // 状态为等待时,定时器时间没到还没执行,此时先把函数压入回调数组,等到时机到了再取出执行
        if (this.status === PM.PENDING) {
            // 2.添加保存执行函数到callbacks数组中
            this.callbacks.push({ onFulfilled, onRejected })
        }
        ...
    }
}

6 pending状态异常处理

测试代码:

<script>
let p = new PM((resolve, reject) => {
   setTimeout(()=>{
       resolve("自定义done")
   },1000)
}).then(value => {
console.log("resolve", abc)
})
</script>

结果报错:

给then方法里的pending状态添加错误处理:

if (this.status === PM.PENDING) {
    this.callbacks.push({
        // 这个onFulfilled是属性名,value是上面resolve方法里执行回调时传进来的值
        onFulfilled: value => {
            try {
                // 这个onFulfilled是then传进来的方法
                onFulfilled(value)
            } catch (error) {
                onRejected(error)
            }
        },
        onRejected: value => {
            try {
                onRejected(value)
            } catch (error) {
                onRejected(error)
            }
        }
    })
}

执行测试代码:

<script>
let p = new PM((resolve, reject) => {
   setTimeout(()=>{
       resolve("自定义done")
   },1000)
}).then(value => {
// 未定义的abc
console.log("resolve", abc)
},reason=>{
  console.log("reject",reason)
})
</script>

测试结果:

7 pending的异步任务处理技巧

先看原生promise:

new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("原生done")
        console.log("定时器")
    }, 1000)
}).then(value => {
    console.log(value)
})
console.log("同步代码")

原生执行结果:

此时相同的测试代码,自定义promise执行结果:

原因:目前的方法,改变状态之后会立刻执行异步方法(也就是then里的resolve),这是不对的。promise的特性就是异步,then里面的函数需要异步执行,这样同步代码(console.log("定时器"))才不会等待它的执行,才能解决等待阻塞。

修改class方法里的部分代码:

resolve(value) {
    if (this.status === PM.PENDING) {
        this.status = PM.FULFILLED;
        this.value = value;
        // 将resolve执行通过setTimeout定义为异步任务
        // 先把它放到任务队列里,等同步的console.log("定时器")跑完之后,下一次再执行
        setTimeout(() => {
            this.callbacks.map(callback => callback.onFulfilled(value))
        })
    }
}

reject(reason) {
    if (this.status === PM.PENDING) {
        this.status = PM.REJECTED;
        this.value = reason;
        // 将reject执行通过setTimeout定义为异步任务
        setTimeout(() => {
            this.callbacks.map(callback => callback.onRejected(reason))
        })
    }
}

8 then链式操作原理分析

Promise中的then是链式调用执行的,所以then也要返回Promise才能实现。

1、then的onReject函数是对前面Promise的rejected的处理;

2、但该Promise返回状态要为fulfilled,所以在调用onRejected后改变当前promise为fulfilled状态。

先看原生promise:

new Promise((resolve, reject) => {
    reject("原生fail")
}).then(value => {
    console.log("1then:", value)
    return "1then 成功参数"
}, reason => {
    console.log("1fail:", reason)
    return "1fail 失败参数"
}).then(value => {
    console.log("2then:", value)
}, reason => {
    console.log("2fail:", reason)
})

结果:

注意点:

每一个then返回的都是一个promise,且状态为解决,不论传给它的是resolve/reject。所以关键的是then方法要返回一个promise,修改代码如下:

class PM {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";

    constructor(executor) {
        this.status = PM.PENDING;
        this.value = null;
        this.callbacks = [];
        try {
            executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
            this.reject(error)
        }
    }

    resolve(value) {
        if (this.status === PM.PENDING) {
            console.log("执行resolve方法")
            this.status = PM.FULFILLED;
            this.value = value;
            setTimeout(() => {
                this.callbacks.map(callback => callback.onFulfilled(value))
            })
        }
    }

    reject(reason) {
        if (this.status === PM.PENDING) {
            console.log("执行reject方法")
            this.status = PM.REJECTED;
            this.value = reason;
            setTimeout(() => {
                this.callbacks.map(callback => callback.onRejected(reason))
            })
        }
    }

    then(onFulfilled, onRejected) {
        console.log("执行then", this)
        if (typeof onFulfilled !== "function") {
            onFulfilled = () => { }
        }
        if (typeof onRejected !== "function") {
            onRejected = () => { }
        }
        // 返回一个promise
        return new PM((resolve, reject) => {
            if (this.status === PM.PENDING) {
                console.log("执行this.status === PM.PENDING")
                this.callbacks.push({
                    onFulfilled: value => {
                        try {
                            onFulfilled(value)
                        } catch (error) {
                            onRejected(error)
                        }
                    },
                    onRejected: value => {
                        try {
                            onRejected(value)
                        } catch (error) {
                            onRejected(error)
                        }
                    }
                })
            }
            if (this.status === PM.FULFILLED) {
                console.log("执行this.status === PM.FULFILLED")
                setTimeout(() => {
                    try {
                        onFulfilled(this.value)
                    } catch (error) {
                        onRejected(error)
                    }
                })
            }
            if (this.status === PM.REJECTED) {
                console.log("执行this.status === PM.REJECTED")
                setTimeout(() => {
                    try {
                        onRejected(this.value)
                    } catch (error) {
                        onRejected(error)
                    }
                })
            }
        })
    }
}

测试代码:

let p = new PM((resolve, reject) => {
    reject("自定义fail")
}).then(value => {
    console.log("1then:", value)
    return "1then 成功参数"
}, reason => {
    console.log("1fail:", reason)
    return "1fail 失败参数"
}).then(value => {
    console.log("2then:", value)
}, reason => {
    console.log("2fail:", reason)
})

结果:

虽然then返回了promise,但是第二个then没有执行,还没有实现链式调用。

原因:第一个then返回的promise是pending状态,没有改变新promise状态为resolve/reject,故而value是构造函数里定义的null。由于没有去改变状态,所以不会执行then方法。

then(onFulfilled, onRejected) {
    ...
    return new PM((resolve, reject) => {
        if (this.status === PM.PENDING) {
            console.log("执行this.status === PM.PENDING")
            this.callbacks.push({
                onFulfilled: value => {
                    try {
                        // 状态变为解决
                        let result = onFulfilled(value)
                        resolve(result) 
                    } catch (error) {
                        onRejected(error)
                    }
                },
                onRejected: value => {
                    try {
                        // 状态变为解决
                        let result = onRejected(value)
                        resolve(result)
                    } catch (error) {
                        onRejected(error)
                    }
                }
            })
        }
        if (this.status === PM.FULFILLED) {
            console.log("执行this.status === PM.FULFILLED")
            setTimeout(() => {
                try {
                    // 状态变为解决
                    let result = onFulfilled(this.value)
                    resolve(result) 
                } catch (error) {
                    onRejected(error)
                }
            })
        }
        if (this.status === PM.REJECTED) {
            console.log("执行this.status === PM.REJECTED")
            setTimeout(() => {
                try {
                    // then返回的propmise状态一律为解决
                    let result = onRejected(this.value)
                    resolve(result) 
                } catch (error) {
                    onRejected(error)
                }
            })
        }
    })
}

测试代码:

let p = new PM((resolve, reject) => {
    resolve("自定义done")
}).then(value => {
    console.log("1then:", value)
    return "1then 成功参数"
}, reason => {
    console.log("1fail:", reason)
    return "1fail 失败参数"
}).then(value => {
    console.log("2then:", value)
}, reason => {
    console.log("2fail:", reason)
})

结果:

9 then新增promise异常处理

原理:所有then里面的出错都交给最后一次then方法的reject函数处理。

return new PM((resolve, reject) => {
    if (this.status === PM.PENDING) {
        this.callbacks.push({
            onFulfilled: value => {
                try {
                    let result = onFulfilled(value)
                    resolve(result)
                } catch (error) {
                    reject(error)
                    // onRejected(error)
                }
            },
            onRejected: value => {
                try {
                    let result = onRejected(value)
                    resolve(result)
                } catch (error) {
                    reject(error)
                    // onRejected(error)
                }
            }
        })
    }
    if (this.status === PM.FULFILLED) {
        setTimeout(() => {
            try {
                let result = onFulfilled(this.value)
                resolve(result)
            } catch (error) {
                reject(error)
                // onRejected(error)
            }
        })
    }
    if (this.status === PM.REJECTED) {
        setTimeout(() => {
            try {
                let result = onRejected(this.value)
                resolve(result)
            } catch (error) {
                reject(error)
                // onRejected(error)
            }
        })
    }
})

10 实现then的穿透传递

先看原生:

new Promise((resolve, reject) => {
    resolve("原生done")
})
.then()
.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})

原生结果:

而自定义的是undefined,此时还没有实现then的透传能力。修改then方法:

if (typeof onFulfilled !== "function") {
    // then传进来的方法为空时,把值返回出去
    onFulfilled = () => this.value
}
if (typeof onRejected !== "function") {
    // then传进来的方法为空时,把值返回出去
    onRejected = () => this.value
}

11 then返回promise的处理

先看原生:

new Promise((resolve, reject) => {
    resolve("原生done")
})
.then(value => {
    return new Promise((resolve) => {
        resolve("返回的值")
    })
})
.then(value => {
    console.log(value)
})

原生执行结果:

而同样的测试,自定义方法结果为:

所以如果then返回的是Promise,需要拿到返回的promise返回的值,而不是它本身。需要判断分别处理返回值为Promise与普通值的情况,修改then代码实现不同类型不同处理机制:

return new PM((resolve, reject) => {
    if (this.status === PM.PENDING) {
        this.callbacks.push({
            onFulfilled: value => {
                try {
                    let result = onFulfilled(value)
                    // 增加返回结果的判断
                    if (result instanceof PM) {
                        result.then(resolve, reject)
                    } else {
                        resolve(result)
                    }
                } catch (error) {
                    reject(error)
                }
            },
            onRejected: value => {
                try {
                    let result = onRejected(value)
                    // 增加返回结果的判断
                    if (result instanceof PM) {
                        result.then(resolve, reject)
                    } else {
                        resolve(result)
                    }
                } catch (error) {
                    reject(error)
                }
            }
        })
    }
    if (this.status === PM.FULFILLED) {
        setTimeout(() => {
            try {
                let result = onFulfilled(this.value)
                // 增加返回结果的判断
                if (result instanceof PM) {
                    // 若是promise,则调用then方法获取它的值,并传给return的new promise(下一个)的resolve/reject
                    result.then(resolve, reject)
                    // 注释代码为优化前,优化原理见下面测试代码注释
                    // result.then(value => {
                    //     resolve(value)
                    // }, reason => {
                    //     reject(reason)
                    // })
                } else {
                    resolve(result)
                }
            } catch (error) {
                reject(error)
            }
        })
    }
    if (this.status === PM.REJECTED) {
        setTimeout(() => {
            try {
                let result = onRejected(this.value)
                // 增加返回结果的判断
                if (result instanceof PM) {
                    result.then(resolve, reject)
                } else {
                    resolve(result)
                }
            } catch (error) {
                reject(error)
            }
        })
    }
})

测试代码:

1 new PM((resolve, reject) => {
2   resolve("自定义done")
3 })
4 .then(value => {
    // 这个promise调用上一个promise的两个函数,来改变状态,然后传给下一个then
    // 核心就是在这个promise的then里把4的then的promise状态改掉
    return new PM((resolve) => {
        resolve("返回的值")
    })
})
.then(value => {
    console.log(value)
})

现在发现pendding、fulfilled、rejected 状态的代码非常相似,所以可以提取出方法Parse来复用。代码优化后:

class PM {
    ...
    then(onFulfilled, onRejected) {
        if (typeof onFulfilled !== "function") {
            onFulfilled = () => this.value
        }
        if (typeof onRejected !== "function") {
            onRejected = () => this.value
        }
        return new PM((resolve, reject) => {
            if (this.status === PM.PENDING) {
                this.callbacks.push({
                    onFulfilled: value => {
                    	// 优化
                        this.parse(onFulfilled(value), resolve, reject)
                    },
                    onRejected: value => {
                    	// 优化
                        this.parse(onRejected(value), resolve, reject)
                    }
                })
            }
            if (this.status === PM.FULFILLED) {
                setTimeout(() => {
                	// 优化
                    this.parse(onFulfilled(this.value), resolve, reject)
                })
            }
            if (this.status === PM.REJECTED) {
                setTimeout(() => {
                    // 优化
                    this.parse(onRejected(this.value), resolve, reject)
                })
            }
        })
    }
    // 抽取通用方法,几处调用只有传进来的result不同,其它都相同
    parse(result, resolve, reject) {
        try {
            if (result instanceof PM) {
                result.then(resolve, reject)
            } else {
                resolve(result)
            }
        } catch (error) {
            reject(error)
        }
    }
}

12 promise返回类型约束

先看原生:

let promise = new Promise((resolve, reject) => {
    resolve("原生done")
})
let p = promise.then(value => {
    // 由于这部分是异步执行,已经生成了p,可以打印p
    console.log("p", p)
})
console.log("同步代码")

原生输出结果:

then返回的promise不能是then相同的Promise,也就是不允许返回自己生成的promise对象。执行以下示例代码将产生错误:

let promise = new Promise((resolve, reject) => {
    resolve("原生done")
})
let p = promise.then(value => {
    // 这里返回本身自己,不允许
    return p
})
console.log("同步代码")

报错:

但是目前自定义的promise不具有这个特性,不会报错。要得到和原生一样的效果,需要添加当前promise作为parse的第一个参数与函数结果比对:

then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== "function") {
        onFulfilled = () => this.value
    }
    if (typeof onRejected !== "function") {
        onRejected = () => this.value
    }
    // 不直接返回,定义一个变量
    let promise = new PM((resolve, reject) => {
        if (this.status === PM.PENDING) {
            this.callbacks.push({
                onFulfilled: value => {
                    // 增加入参promise,由于异步执行,所以可读取到上面定义的promise
                    this.parse(promise, onFulfilled(value), resolve, reject)
                },
                onRejected: value => {
                    // 增加入参promise
                    this.parse(promise, onRejected(value), resolve, reject)
                }
            })
        }
        if (this.status === PM.FULFILLED) {
            setTimeout(() => {
                // 增加入参promise
                this.parse(promise, onFulfilled(this.value), resolve, reject)
            })
        }
        if (this.status === PM.REJECTED) {
            setTimeout(() => {
                // 增加入参promise
                this.parse(promise, onRejected(this.value), resolve, reject)
            })
        }
    })
    // 在这里返回变量
    return promise
}

parse(promise, result, resolve, reject) {
    // 增加判断,相等则报错
    if (promise === result) {
        throw new TypeError("Chaining cycle detected")
    }
    try {
        if (result instanceof PM) {
            result.then(resolve, reject)
        } else {
            resolve(result)
        }
    } catch (error) {
        reject(error)
    }
}

13 实现resolve与reject静态方法

实现promise静态方法:

Promise.resolve("原生done").then(value => {
    console.log(value)
})
Promise.reject("原生fail").then(null, reason => {
    console.log(reason)
})

在自定class里增加静态方法,核心是返回一个promise:

static resolve(value) {
    return new PM((resolve, reject) => {
        // 需要改变promise状态,不然then不会对它进行处理
        resolve(value)
    })
}

再看原生,如果传入的是promise,那么这个promise状态决定了then执行哪一个方法,resolve走成功方法,reject走失败方法。

let p = new Promise((resolve, reject) => {
    reject("原生fail1")
})
Promise.resolve(p).then(value => {
    console.log("成功", value)
}, reason => {
    console.log("失败", reason)
})

原生结果:

再次修改刚才的静态方法,顺便加上reject:

static resolve(value) {
    return new PM((resolve, reject) => {
        if (value instanceof PM) {
            value.then(resolve, reject)
        } else {
            resolve(value)
        }
    })
}
static reject(value) {
    return new PM((resolve, reject) => {
        reject(value)
    })
}

14 promise的all静态方法实现

先看原生:

let p1 = new Promise((resolve, reject) => {
    resolve("原生p1")
})
let p2 = new Promise((resolve, reject) => {
    resolve("原生p2")
})
Promise.all([p1, p2]).then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
// 输出 ["原生p1", "原生p2"]
// 有任何一个reject就走到reject,只取第一个reject
let p1 = new Promise((resolve, reject) => {
    resolve("原生p1")
})
let p2 = new Promise((resolve, reject) => {
    reject("原生p2")
})
Promise.all([p1, p2]).then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
// 输出 原生p2

自定义方法实现,在class里添加静态方法:

static all(promises) {
    return new PM((resolve, reject) => {
        const values = [];
        promises.forEach(promise => {
            promise.then(value => {
                values.push(value)
                // 全部成功才resolve
                if (values.length === promises.length) {
                    resolve(values)
                }
            }, reason => {
                // 只要有一个失败就reject
                reject(reason)
            })
        })
    })
}

15 promise的race静态方法实现

先看原生:

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject("原生p1")
    }, 2000)
})
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject("原生p2")
    }, 1000)
})
Promise.race([p1, p2]).then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
// 谁快用谁。输出 原生p2

自定义实现,在class里添加静态方法:

static race(promises) {
    return new PM((resolve, reject) => {
        promises.map(promise => {
           // 状态一旦改变就不会再执行了,所以达到了谁先用谁
            promise.then(value => {
                resolve(value)
            }, reason => {
                reject(reason)
            })
        })
    })
}

完整实现代码

class PM {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";

    constructor(executor) {
        this.status = PM.PENDING;
        this.value = null;
        this.callbacks = [];
        try {
            executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
            this.reject(error)
        }
    }

    resolve(value) {
        if (this.status === PM.PENDING) {
            this.status = PM.FULFILLED;
            this.value = value;
            setTimeout(() => {
                this.callbacks.map(callback => {
                    callback.onFulfilled(value)
                })
            })
        }
    }

    reject(reason) {
        if (this.status === PM.PENDING) {
            this.status = PM.REJECTED;
            this.value = reason;
            setTimeout(() => {
                this.callbacks.map(callback => callback.onRejected(reason))
            })
        }
    }

    then(onFulfilled, onRejected) {
        if (typeof onFulfilled !== "function") {
            onFulfilled = () => this.value
        }
        if (typeof onRejected !== "function") {
            onRejected = () => this.value
        }
        let promise = new PM((resolve, reject) => {
            if (this.status === PM.PENDING) {
                this.callbacks.push({
                    onFulfilled: value => {
                        this.parse(promise, onFulfilled(value), resolve, reject)
                    },
                    onRejected: value => {
                        this.parse(promise, onRejected(value), resolve, reject)
                    }
                })
            }
            if (this.status === PM.FULFILLED) {
                setTimeout(() => {
                    this.parse(promise, onFulfilled(this.value), resolve, reject)
                })
            }
            if (this.status === PM.REJECTED) {
                setTimeout(() => {
                    this.parse(promise, onRejected(this.value), resolve, reject)
                })
            }
        })
        return promise
    }

    parse(promise, result, resolve, reject) {
        if (promise === result) {
            throw new TypeError("Chaining cycle detected")
        }
        try {
            if (result instanceof PM) {
                result.then(resolve, reject)
            } else {
                resolve(result)
            }
        } catch (error) {
            reject(error)
        }
    }

    static resolve(value) {
        return new PM((resolve, reject) => {
            if (value instanceof PM) {
                value.then(resolve, reject)
            } else {
                resolve(value)
            }
        })
    }
    static reject(value) {
        return new PM((resolve, reject) => {
            reject(value)
        })
    }
    static all(promises) {
        return new PM((resolve, reject) => {
            const values = [];
            promises.forEach(promise => {
                promise.then(value => {
                    values.push(value)
                    if (values.length === promises.length) {
                        resolve(values)
                    }
                }, reason => {
                    reject(reason)
                })
            })
        })
    }
    static race(promises) {
        return new PM((resolve, reject) => {
            promises.map(promise => {
                promise.then(value => {
                    resolve(value)
                }, reason => {
                    reject(reason)
                })
            })
        })
    }
}

如有错误,请帮忙指正~

参考教程:www.houdunren.com/Edu/video/1…