# 手写 Promise

# 构造函数

核心步骤

定义类 => 添加构造函数 => 定义resolve/reject => 执行回调函数
class MyPromise {
    // state = PENDING;
    // result = undefined;
    constructor(executor) {
        const resolve = (value) => {
        }
        const reject = (reason) => {
        }
        executor(resolve, reject);
    }
}

# 状态及原因

核心步骤

添加状态 => 添加原因 => 调整resolve/reject => 状态不可逆
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected';
class MyPromise {
    state = PENDING;
    result = undefined;
    constructor(executor) {
        // 改状态: pending -> fulfilled
        const resolve = (value) => {
            if(this.state === PENDING) {
                this.state = FULFILLED;
                this.result = value;
            }
        }
        // 改状态: pending -> rejected
        const reject = (reason) => {
            if(this.state === PENDING) {
                this.state = REJECTED;
                this.result = reason;
            }
        }
        executor(resolve, reject);
    }
}
const p = new MyPromise((resolve, reject) => {
    resolve('success');
});
console.log(p);

# then 方法

# 成功或失败回调

根据当前的状态,执行对应的回调函数。特殊的如果传入的回调函数不是函数,返回原值
核心步骤

添加实例方法 => 参数判断 => 执行成功/失败回调
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected';
class MyPromise {
    state = PENDING;
    result = undefined;
    constructor(executor) {
        // 改状态: pending -> fulfilled
        const resolve = (value) => {
            if(this.state === PENDING) {
                this.state = FULFILLED;
                this.result = value;
            }
        }
        // 改状态: pending -> rejected
        const reject = (reason) => {
            if(this.state === PENDING) {
                this.state = REJECTED;
                this.result = reason;
            }
        }
        executor(resolve, reject);
    }
    then(onFulfilled, onRejected) {
        // 如果 then 传入的参数不是函数,参考 MDN 文档返回
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
        if(this.state === FULFILLED) {
            onFulfilled(this.result);
        } else if(this.state === REJECTED) {
            onRejected(this.result);
        }
    }
}
const p = new MyPromise((resolve, reject) => {
    resolve('success');
});
p.then(res => {
    console.log(res);
}, err => {
    console.log(err);
})
console.log(p);

# 异步和多次调用

根据当前的状态,如果是 pending,先将回调函数保存起来,等状态改变后,再执行回调函数。如果多次调用 then,将回调函数保存起来,等状态改变后,再执行回调函数。
核心步骤

定义实例属性 => 保存回调函数 => 执行成功/失败回调
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected';
class MyPromise {
    state = PENDING;
    result = undefined;
    #handlers = []; // [{onFulfilled, onRejected}, 。。。]
    constructor(executor) {
        // 改状态: pending -> fulfilled
        const resolve = (value) => {
            if(this.state === PENDING) {
                this.state = FULFILLED;
                this.result = value;
                // 执行回调
                this.#handlers.forEach(({onFulfilled}) => { 
                    onFulfilled(this.result);
                })
            }
        }
        // 改状态: pending -> rejected
        const reject = (reason) => {
            if(this.state === PENDING) {
                this.state = REJECTED;
                this.result = reason;
                // 执行回调
                this.#handlers.forEach(({onRejected}) => { 
                    onRejected(this.result);
                })
            }
        }
        executor(resolve, reject);
    }
    then(onFulfilled, onRejected) {
        // 如果 then 传入的参数不是函数,参考 MDN 文档返回
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
        if(this.state === FULFILLED) {
            onFulfilled(this.result);
        } else if(this.state === REJECTED) {
            onRejected(this.result);
        } else if(this.state === PENDING) {
            this.#handlers.push({
                onFulfilled,
                onRejected
            })
        }
    }
}
const p = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('success');
    }, 1000);
});
p.then(res => {
    console.log(res);
}, err => {
    console.log(err);
})
p.then(res => {
    console.log(res);
}, err => {
    console.log(err);
})
console.log(p);

# 异步任务

先执行宏队列,再执行微队列。
而 Promise 是异步的,所以先执行微队列,再执行宏队列。
核心步骤

定义函数 => 调用核心API => 调用函数
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected';
class MyPromise {
    state = PENDING;
    result = undefined;
    #handlers = []; // [{onFulfilled, onRejected}, 。。。]
    constructor(executor) {
        // 改状态: pending -> fulfilled
        const resolve = (value) => {
            if(this.state === PENDING) {
                this.state = FULFILLED;
                this.result = value;
                // 执行回调
                this.#handlers.forEach(({onFulfilled}) => { 
                    onFulfilled(this.result);
                })
            }
        }
        // 改状态: pending -> rejected
        const reject = (reason) => {
            if(this.state === PENDING) {
                this.state = REJECTED;
                this.result = reason;
                // 执行回调
                this.#handlers.forEach(({onRejected}) => { 
                    onRejected(this.result);
                })
            }
        }
        executor(resolve, reject);
    }
    then(onFulfilled, onRejected) {
        // 如果 then 传入的参数不是函数,参考 MDN 文档返回
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
        if(this.state === FULFILLED) {
            runAsynctask(() => {
                onFulfilled(this.result);
            })
        } else if(this.state === REJECTED) {
            runAsynctask(() => {
                onRejected(this.result);
            })
        } else if(this.state === PENDING) {
            this.#handlers.push({
                onFulfilled: () => {
                    runAsynctask(() => {
                        onFulfilled(this.result);
                    })
                },
                onRejected: () => {
                    runAsynctask(() => {
                        onRejected(this.result);
                    })
                }
            })
        }
    }
}
function runAsynctask(callback) {
    if(typeof queueMicrotask === 'function') {
        queueMicrotask(callback);
    } else if(typeof MutationObserver === 'function') {
        const obs = new MutationObserver(callback);
        const divNode = document.createElement('div');
        obs.observe(divNode, {childList: true})
        divNode.innerText = '1';
    } else {
        setTimeout(callback, 0);
    }
}
const p = new MyPromise((resolve, reject) => {
    resolve('success')
})
p.then(res => {
    console.log(res);
})
console.log('end');

# 总结

  1. 构造函数
    构造函数接收一个执行器函数 executor ,该函数接收两个参数: resolvereject 。这两个函数分别用于将 Promise 的状态从 pending 转变为 fulfilledrejected
class MyPromise {
    state = PENDING;           // 当前状态,默认为 pending
    result = undefined;        // 存储 resolve 或 reject 的结果
    #handlers = [];            // 存储 then 方法中注册的回调函数
    constructor(executor) {
        const resolve = (value) => {
            if (this.state === PENDING) { // 确保状态只能从 pending 转变为 fulfilled
                this.state = FULFILLED;
                this.result = value;
                // 触发所有已注册的 onFulfilled 回调
                this.#handlers.forEach(({ onFulfilled }) => {
                    onFulfilled(this.result);
                });
            }
        };
        const reject = (reason) => {
            if (this.state === PENDING) { // 确保状态只能从 pending 转变为 rejected
                this.state = REJECTED;
                this.result = reason;
                // 触发所有已注册的 onRejected 回调
                this.#handlers.forEach(({ onRejected }) => {
                    onRejected(this.result);
                });
            }
        };
        try {
            executor(resolve, reject);
        } catch (err) {
            reject(err); // 如果执行器抛出异常,则直接调用 reject
        }
    }
}
  1. then 方法
    then 方法允许我们为 Promise 注册成功和失败的回调函数。无论当前 Promise 的状态是 fulfilled 还是 rejectedthen 方法都会触发相应的回调。如果 Promise 仍然处于 pending 状态,则会将回调存储起来,等到状态改变时再执行。
then(onFulfilled, onRejected) {
    // 如果 then 的参数不是函数,则提供默认实现
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
    const p2 = new MyPromise((resolve, reject) => {
        if (this.state === FULFILLED) {
            runAsynctask(() => {
                try {
                    const x = onFulfilled(this.result);
                    resolvePromise(p2, x, resolve, reject);
                } catch (err) {
                    reject(err);
                }
            });
        } else if (this.state === REJECTED) {
            runAsynctask(() => {
                try {
                    const x = onRejected(this.result);
                    resolvePromise(p2, x, resolve, reject);
                } catch (error) {
                    reject(error);
                }
            });
        } else if (this.state === PENDING) {
            this.#handlers.push({
                onFulfilled: () => {
                    runAsynctask(() => {
                        try {
                            const x = onFulfilled(this.result);
                            resolvePromise(p2, x, resolve, reject);
                        } catch (err) {
                            reject(err);
                        }
                    });
                },
                onRejected: () => {
                    runAsynctask(() => {
                        try {
                            const x = onRejected(this.result);
                            resolvePromise(p2, x, resolve, reject);
                        } catch (err) {
                            reject(err);
                        }
                    });
                }
            });
        }
    });
    return p2; // 返回新的 Promise
}
  1. 静态方法
    为了方便使用,还实现了两个静态方法 resolvereject ,它们可以快速创建一个已经或拒绝的 Promise
static resolve(value) {
    if (value instanceof MyPromise) {
        return value;
    } else {
        return new MyPromise((resolve) => {
            resolve(value);
        });
    }
}
static reject(reason) {
    return new MyPromise((resolve, reject) => {
        reject(reason);
    });
}
  1. 解析返回值函数
    then 方法中的回调函数返回一个值时,我们需要决定如何处理这个值。如果返回的是另一个 Promise ,我们需要等待它的状态变化;否则,直接使用这个值作为新 Promise 的结果
function resolvePromise(p2, x, resolve, reject) {
    if (p2 === x) {
        throw new TypeError('Chaining cycle detected for promise');
    }
    if (x instanceof MyPromise) {
        x.then(res => {
            resolve(res);
        }, (err) => {
            reject(err);
        });
    } else {
        resolve(x);
    }
}
  1. 异步任务
    为了确保回调函数总是异步执行,我们使用了一个辅助函数 runAsynctask 来调度任务,优先尝试使用 queueMicrotask ,如果不支持则回退到 MutationObserversetTimeout
function runAsynctask(callback) {
    if (typeof queueMicrotask === 'function') {
        queueMicrotask(callback);
    } else if (typeof MutationObserver === 'function') {
        const obs = new MutationObserver(callback);
        const divNode = document.createElement('div');
        obs.observe(divNode, { childList: true });
        divNode.innerText = '1';
    } else {
        setTimeout(callback, 0);
    }
}
  1. 代码
// 三种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected';
class MyPromise {
    state = PENDING;
    result = undefined;
    #handlers = []; // 存储 then 方法中注册的回调函数 [{onFulfilled, onRejected}, 。。。]
    /**
     * 构造函数,初始化 Promise
     * @param {Function} executor - 执行器函数,接收 resolve 和 reject 作为参数
     */
    constructor(executor) {
        // 改状态: pending -> fulfilled
        const resolve = (value) => {
            if (this.state === PENDING) { // 确保状态只能从 pending -> fulfilled
                this.state = FULFILLED; // 更新
                this.result = value; // 更新
                // 触发所有已注册的回调函数
                this.#handlers.forEach(({ onFulfilled }) => {
                    onFulfilled(this.result);
                })
            }
        }
        // 改状态: pending -> rejected
        const reject = (reason) => {
            if (this.state === PENDING) { // 确保状态只能从 pending -> rejected
                this.state = REJECTED;
                this.result = reason;
                // 触发所有已注册的回调函数
                this.#handlers.forEach(({ onRejected }) => {
                    onRejected(this.result);
                })
            }
        }
        try {
            // 执行用户传入的执行器函数,传入 resolve 和 reject
            executor(resolve, reject);
        } catch (err) {
            // 如果执行器函数执行出错,则调用 reject
            reject(err);
        }
    }
    /**
     * 注册成功和失败的回调函数
     * @param {Function} onFulfilled - 成功时的回调函数
     * @param {Function} onRejected - 失败时的回调函数
     * @returns {MyPromise} 返回一个新的 Promise 对象
     */
    then(onFulfilled, onRejected) {
        // 如果 then 传入的参数不是函数,参考 MDN 文档返回
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
        // 返回新的 promise
        const p2 = new MyPromise((resolve, reject) => {
            if (this.state === FULFILLED) {
                // 当前状态为 fulfilled,则直接调用 onFulfilled
                runAsynctask(() => {
                    try {
                        const x = onFulfilled(this.result); // 执行回调函数
                        resolvePromise(p2, x, resolve, reject); // 解析回调函数的返回值
                    } catch (err) {
                        reject(err);
                    }
                })
            } else if (this.state === REJECTED) {
                // 当前状态为 rejected,则直接调用 onRejected
                runAsynctask(() => {
                    try {
                        const x = onRejected(this.result); // 执行回调函数
                        resolvePromise(p2, x, resolve, reject); // 解析回调函数的返回值
                    } catch (error) {
                        reject(error);
                    }
                })
            } else if (this.state === PENDING) {
                // 当前状态为 pending,则将回调函数存储起来,待状态改变时再执行
                this.#handlers.push({
                    onFulfilled: () => {
                        runAsynctask(() => {
                            try {
                                const x = onFulfilled(this.result);
                                resolvePromise(p2, x, resolve, reject);
                            } catch (err) {
                                reject(err);
                            }
                        })
                    },
                    onRejected: () => {
                        runAsynctask(() => {
                            try {
                                const x = onRejected(this.result);
                                resolvePromise(p2, x, resolve, reject);
                            } catch (err) {
                                reject(err);
                            }
                        })
                    }
                })
            }
        });
        return p2; // 返回新的 promise
    }
    /**
     * 注册失败的回调函数
     * @param {Function} onRejected - 失败时的回调函数
     * @returns {MyPromise} 返回一个新的 Promise 对象
     */
    catch(onRejected) {
        return this.then(null, onRejected);
    }
    /**
     * 注册无论成功或失败都会执行的回调函数
     * @param {Function} callback - 无论成功或失败都会执行的回调函数
     * @returns {MyPromise} 返回一个新的 Promise 对象
     */    
    finally(callback) {
        return this.then(callback, callback); // 无论成功或失败都会执行
    }
    /**
     * 将传入的值转为一个 resolved 状态的 Promise
     * @param {*} value - 需要转换的值
     * @returns {MyPromise} 返回一个 resolved 状态的 Promise
     */
    static resolve(value) {
        if (value instanceof MyPromise) {
            return value; // 如果已经是一个 Promise 对象,直接返回
        } else {
            return new MyPromise((resolve) => {
                resolve(value); // 转换为 resolved 状态
            })
        }
    }
    /**
     * 返回一个 rejected 状态的 Promise
     * @param {*} reason - 拒绝的原因
     * @returns {MyPromise} 返回一个 rejected 状态的 Promise
     */
    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason); // 创建一个新的 rejected Promise
        })
    }
}
/**
 * 解析 Promise 的返回值 x,并决定如何更新新的 Promise p2 的状态
 * @param {MyPromise} p2 - 新的 Promise 对象
 * @param {*} x - then 回调函数的返回值
 * @param {Function} resolve - p2 的 resolve 函数
 * @param {Function} reject - p2 的 reject 函数
 */
function resolvePromise(p2, x, resolve, reject) {
    if (p2 === x) {
        // 如果 x 是 p2 本身,抛出循环引用错误
        throw new TypeError('Chaining cycle detected for promise');
    }
    if (x instanceof MyPromise) {
        // 如果 x 是一个 Promise 递归解析状态
        x.then(res => {
            resolve(res);
        }, (err) => {
            reject(err);
        })
    } else {
        resolve(x);
    }
}
/**
 * 异步执行任务(微任务优先)
 * @param {Function} callback - 需要异步执行的任务
 */
function runAsynctask(callback) {
    if (typeof queueMicrotask === 'function') {
        queueMicrotask(callback);
    } else if (typeof MutationObserver === 'function') {
        const obs = new MutationObserver(callback);
        const divNode = document.createElement('div');
        obs.observe(divNode, { childList: true })
        divNode.innerText = '1';
    } else {
        setTimeout(callback, 0);
    }
}
更新于 阅读次数