让我们一起构建一个简化的 Promise 版本,并讲解其核心原理。
Promise 的核心思想
Promise 代表一个异步操作的最终结果。它可以处于三种状态:
- Pending(进行中): 初始状态,表示异步操作尚未完成。
- Fulfilled(已成功): 表示异步操作成功完成,并带有一个结果值。
- Rejected(已失败): 表示异步操作失败,并带有一个错误原因。
Promise 允许你使用 then() 方法来注册回调函数,这些回调函数会在 Promise 状态改变时被调用。
简化的 Promise 实现
function MyPromise(executor) {
this.status = 'pending'; // 初始状态为 pending
this.value = undefined; // 存储成功的结果
this.reason = undefined; // 存储失败的原因
this.onFulfilledCallbacks = []; // 存储成功的回调函数
this.onRejectedCallbacks = []; // 存储失败的回调函数
const resolve = (value) => {
if (this.status === 'pending') {
this.status = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback(this.value));
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback(this.reason));
}
};
try {
executor(resolve, reject); // 执行传入的 executor 函数
} catch (error) {
reject(error); // 捕获 executor 执行过程中的错误
}
}
MyPromise.prototype.then = function(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函数,提供一个默认函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// 如果 onRejected 不是函数,提供一个抛出错误的默认函数
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
let promise2; // 用于返回新的 Promise
if (this.status === 'fulfilled') {
promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => { // 使用 setTimeout 确保异步执行
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject); // 处理 then 返回值
} catch (error) {
reject(error);
}
});
});
}
if (this.status === 'rejected') {
promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if (this.status === 'pending') {
promise2 = new MyPromise((resolve, reject) => {
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
const x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
const x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
});
}
return promise2;
};
function resolvePromise(promise2, x, resolve, reject) {
// 防止循环引用
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 如果 x 是一个 Promise,根据它的状态决定 promise2 的状态
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 如果 x 是对象或函数,尝试提取 then 方法
let called = false;
try {
const then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x); // 如果 x 不是 thenable,直接 resolve
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x); // x 不是对象或函数,直接 resolve
}
}
// 测试
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Success!');
}, 1000);
});
promise.then(value => {
console.log(value); // 输出: Success!
return 'Another value';
}).then(value => {
console.log(value); // 输出: Another value
});
原理讲解
-
构造函数
MyPromise:- 初始化 Promise 的状态为
pending,结果value和原因reason为undefined。 - 创建两个数组
onFulfilledCallbacks和onRejectedCallbacks用于存储成功和失败的回调函数。 - 接收一个
executor函数作为参数,该函数会在创建 Promise 时立即执行。 executor函数接收两个参数resolve和reject,用于改变 Promise 的状态。resolve函数将状态改为fulfilled,设置结果value,并执行所有onFulfilledCallbacks中的回调函数。reject函数将状态改为rejected,设置原因reason,并执行所有onRejectedCallbacks中的回调函数。- 使用
try...catch捕获executor执行过程中可能出现的错误,并调用reject抛出错误。
- 初始化 Promise 的状态为
-
then方法:- 接收两个可选参数
onFulfilled和onRejected,分别表示成功和失败的回调函数。 - 如果
onFulfilled或onRejected不是函数,则提供默认函数。 - 创建一个新的 Promise
promise2作为then方法的返回值,用于实现链式调用。 - 根据当前 Promise 的状态:
- 如果是
fulfilled,则异步执行onFulfilled回调函数,并将返回值传递给resolvePromise处理。 - 如果是
rejected,则异步执行onRejected回调函数,并将返回值传递给resolvePromise处理。 - 如果是
pending,则将onFulfilled和onRejected回调函数分别添加到onFulfilledCallbacks和onRejectedCallbacks数组中,等待 Promise 状态改变时执行。
- 如果是
- 返回
promise2。
- 接收两个可选参数
-
resolvePromise函数:- 处理
then方法中回调函数的返回值,决定promise2的最终状态和结果。 - 防止循环引用:如果
promise2和x是同一个对象,则抛出类型错误。 - 如果
x是一个 Promise,则根据x的状态来改变promise2的状态。 - 如果
x是一个 thenable 对象(具有then方法的对象或函数),则尝试调用then方法,根据then的回调结果来改变promise2的状态。 - 如果
x不是 thenable,则直接将promise2resolve 为x的值。
- 处理
重要概念
- 异步执行: 使用
setTimeout确保回调函数在事件循环的下一个循环中执行,从而实现异步。 - 链式调用:
then方法返回一个新的 Promise,使得可以链式调用多个then方法。 - 错误处理: 使用
try...catch捕获错误,并在reject中传递错误原因。
这个简化的 Promise 实现涵盖了 Promise 的核心原理,但它并不包含所有细节。例如,实际的 Promise 实现还需要处理更复杂的错误情况和微任务队列。 然而,通过理解这个简单的实现,你可以更好地理解 Promise 的工作方式。