编辑代码

// 工具函数 handleValue 来专门处理实例方法 then 返回的值(类型的判断以及对应的处理)
const handleValue = (promise2, x, resolve, reject) => {
    // 循环引用,自己等待自己完成,会出错,用reject传递出错误原因
    if (promise2 === x) {
        return reject(new TypeError('检测到Promise的链式循环引用'))
    }
    // 为了判断resolve过的就不用再reject了(比如有reject和resolve的时候),确保递归解析中只传递出去一次值
    let once = false;
    //如果x不是null,是对象或者方法
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            // 防止重复去读取x.then
            let then = x.then;
            // 判断x是不是Promise
            if (typeof then === 'function') {
                // 是promise,call他,第一个参数指定x这个promise对象作为then方法的this上下文,所以then方法中的this来自自己的promise对象x
                // 调用then实例方法处理Promise执行结果
                then.call(x, y => {
                    if (once) return;
                    once = true;
                    // 防止Promise中Promise执行成功后又传递一个Promise过来,要做递归解析。
                    // handleValue(promise2, y, resolve, reject);
                    resolve(y) // 结果当作promise2的resolve结果,此时resolve中的this指向promise2
                }, r => {
                    if (once) return;
                    once = true;
                    // 一次错误就直接返回
                    reject(r); // 失败原因当作promise2的reject失败原因,此时reject中的this指向promise2
                })
            } else {
                // 如果x是个普通对象,直接调用resolve(x)
                resolve(x);
            }
        } catch (err) {
            if (once) return;
            once = true;
            reject(err);
        }
    } else {
        // 如果x是个原始值,直接调用resolve(x)
        resolve(x);
    }
}
// 在这里用Symbol定义三种状态,防止外部改变状态
const Pending = Symbol('Pending'); // 进行中
const Fulfilled = Symbol('Fulfilled'); // 已成功
const Rejected = Symbol('Rejected'); // 已失败
class Promise {
    constructor(executor) {
        this.status = Pending; //存储 Promise 的状态
        this.value = undefined; //存储executor函数中业务代码执行成功的结果
        this.reason = undefined; //存储executor函数中业务代码执行失败的原因
        this.onFulfilled = []; //executor函数中业务代码执行成功回调函数的集合
        this.onRejected = []; //executor函数中业务代码执行失败回调函数的集合
        const resolve = value => {
            // Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected
            // 只有当状态为 Pending 才会改变,来保证一旦状态改变就不会再变。
            if (this.status === Pending) {
                this.status = Fulfilled;
                this.value = value;
                // 依次调用成功回调函数
                this.onFulfilled.forEach(fn => fn());
            }
        };
        const reject = value => {
            // 只有当状态为 Pending 才会改变,来保证一旦状态改变就不会再变。
            if (this.status === Pending) {
                this.status = Rejected;
                this.reason = value;
                // 依次调用失败回调函数
                this.onRejected.forEach(fn => fn());
            }
        };
        try {
            //将resolve和reject两个函数作为参数传入executor
            executor(resolve, reject);
        } catch (error) {
            //如果在函数中抛出异常则将它注入reject中
            reject(error)
        }

    }
    // PS: 1、then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例),
    // 第一个参数是fulfilled(已成功)状态的回调函数,第二个参数(可选)是rejected(已失败)状态的回调函数
    // 因此可以采用链式写法,即then方法后面再调用另一个then方法。
    // 2、用 try ... catch 语句来捕获错误,把错误用内置方法传递出去 reject,防止 Promise 内部执行错误无法追踪
    then(onFulfilled, onRejected) {
        //解决onFufilled,onRejected没有传值的问题,实现then值的穿透
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
        //因为错误的值要让后面访问到,所以这里也要抛出个错误,不然会在之后then的resolve中捕获
        onRejected = typeof onRejected === 'function' ? onRejected : err => {
            throw err
        };;
        let promise2 = new Promise((resolve, reject) => {
            if (this.status === Fulfilled) {
                // 由于原生的 Promise 是V8引擎提供的微任务,我们无法还原V8引擎的实现,
                // 所以这里使用 setTimeout 模拟异步,所以原生的Promise.then()是微任务,这里是宏任务。
                setTimeout(() => {
                    try {
                        // 因为有的时候需要判断then中的方法是否返回另一个promise对象(即有异步操作),
                        // 这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用,
                        // 所以需要判断,如果返回值为promise对象,则需要取出结果当作promise2的resolve结果
                        // 如果不是,直接作为promise2的resolve结果
                        let x = onFulfilled(this.value);
                        // 抽离出一个公共方法来判断他们是否为promise对象
                        handleValue(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            }
            if (this.status === Rejected) {
                if (onRejected && typeof onRejected === 'function') {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            handleValue(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                }
            }
            if (this.status === Pending) {
                // 添加订阅者,观察者模式解决异步调用问题(控制 then 实例方法中回调函数的执行时机)
                this.onFulfilled.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            handleValue(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                })
                if (onRejected && typeof onRejected === 'function') {
                    this.onRejected.push(() => {
                        setTimeout(() => {
                            try {
                                let x = onRejected(this.reason);
                                handleValue(promise2, x, resolve, reject);
                            } catch (error) {
                                reject(error)
                            }
                        }, 0)
                    })
                }
            }
        })
        return promise2
    }
    // //catch方法
    // catch(onRejected) {
    //     this.then(null, onRejected)
    // }
    //finally方法
    // finally(callback) {
    //     let P = this.constructor;
    //     return this.then(
    //         value => P.resolve(callback()).then(() => value),
    //         reason => P.resolve(callback()).then(() => { throw reason })
    //     );
    // }
    // static resolve(param) {
    //     if (param instanceof Promise) {
    //         return param;
    //     }
    //     return new Promise((resolve, reject) => {
    //         if (
    //             param &&
    //             Object.prototype.toString.call(param) === '[object Object]' &&
    //             typeof param.then === 'function'
    //         ) {
    //             setTimeout(() => {
    //                 param.then(resolve, reject)
    //             }, 0)
    //         } else {
    //             resolve(param)
    //         }
    //     })
    // }
    // static reject(param) {
    //     return new Promise((resolve, reject) => {
    //         reject(param)
    //     })
    // }
    // static all(promises) {
    //     //将参数promises转为一个真正的数组
    //     promises = Array.from(promises);
    //     return new Promise((resolve, reject) => {
    //         const length = promises.length;
    //         let value = [];
    //         if (length) {
    //             value = Array.apply(null, {
    //                 length: length
    //             })
    //             for (let i = 0; i < length; i++) {
    //                 Promise.resolve(promises[i]).then(
    //                     res => {
    //                         value[i] = res;
    //                         if (value.length == length) {
    //                             resolve(value);
    //                         }
    //                     },
    //                     err => {
    //                         reject(err)
    //                         return;
    //                     }
    //                 )
    //             }
    //         } else {
    //             resolve(value)
    //         }
    //     })
    // }
    // static race(promises) {
    //     //将参数promises转为一个真正的数组
    //     promises = Array.from(promises);
    //     return new Promise((resolve, reject) => {
    //         const length = promises.length;
    //         if (length) {
    //             for (let i = 0; i < length; i++) {
    //                 Promise.resolve(promises[i]).then(
    //                     res => {
    //                         resolve(res);
    //                         return;
    //                     },
    //                     err => {
    //                         reject(err)
    //                         return;
    //                     }
    //                 )
    //             }
    //         } else {
    //             return
    //         }
    //     })
    // }
}

const test = new Promise((resolve, reject) => {
    resolve('"执行成功"')
})
test.then(res => {
    console.log(res)
})
console.log(Object.prototype.toString.call(test))