完整代码:
class MyPromise {
constructor(executor) {
// 状态:pending、fulfilled、rejected
this.state = 'pending';
this.value = undefined; // 成功时的值
this.reason = undefined; // 失败时的原因
this.onFulfilledCallbacks = []; // 成功时的回调队列
this.onRejectedCallbacks = []; // 失败时的回调队列
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 使用try-catch捕获执行器中的同步错误
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then 方法
then(onFulfilled, onRejected) {
// 处理参数可选性
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };
// 实现链式调用
let promise2 = new MyPromise((resolve, reject) => {
const handleCallback = (callback, value) => {
setTimeout(() => {
try {
let x = callback(value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.state === 'fulfilled') {
handleCallback(onFulfilled, this.value);
} else if (this.state === 'rejected') {
handleCallback(onRejected, this.reason);
} else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => handleCallback(onFulfilled, this.value));
this.onRejectedCallbacks.push(() => handleCallback(onRejected, this.reason));
}
});
return promise2
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(onFinally) {
return this.then(
value => MyPromise.resolve(onFinally()).then(() => value),
reason => MyPromise.resolve(onFinally().then(() => { throw reason; })
);
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new Promise((resolve, reject) =>
reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let remaining = promises.length;
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
remaining--;
if (remaining == 0) {
resolve(results);
}
},
reason => reject(reason)
);
});
});
}
static race(promise) {
return new MyPromise((resolve, reject) => {
promise.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
}
// resolvePromise函数
// 处理循环引用
// used 确保thenable的then方法只调用一次
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 如果x是promise,递归解包直到非promise值
if (x instanceof MyPromise) {
x.then(y => resolvePromise(promise2, y, resolve, reject), reject);
return;
}
// 如果x是thenable对象,具有then的方法的对象或函数,调用其then方法
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let used;
try {
let then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
if (used) return;
used = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (used) return;
used = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (error) {
if (used) return;
used = true;
reject(error);
}
}
else {
resolve(x);
}
}
逐步分析
定义属性。
回调队列用于存储 .then()
注册的异步回调,当状态改变时统一执行。
executor
是创建 Promise 时传入的函数(此时为形参)
constructor(executor) {
// 状态:pending、fulfilled、rejected
this.state = 'pending';
this.value = undefined; // 成功时的值
this.reason = undefined; // 失败时的原因
this.onFulfilledCallbacks = []; // 成功时的回调队列
this.onRejectedCallbacks = []; // 失败时的回调队列
只有在 pending
状态下才能改变状态(确保状态不可逆)。
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
// 执行所有通过 .then() 注册的成功回调(这些回调是在 pending 时注册的)。
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
reject 函数与 resolve 函数类似,区别在于该函数保存返回的是失败原因,并执行所有失败回调。
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
executor(resolve, reject)
表示执行传入的执行器函数,并以 resolve, reject 为参数。
以 resolve, reject为参数时,这是两个函数参数,这两个函数用于改变 Promise 的状态,并且把 value 或 reason 保存起来,供.then()
或.catch()
调用。
try {
executor(resolve, reject);
} catch (error) {
reject(error); // 如果 executor 内部出错,直接 reject
}
.then
方法用来听通知:Promise什么时候成功 / 失败,成功做了什么 / 做什么失败了。所有Promise实例必须有 .then
方法。只有表示异步操作结果的对象才需要.then
。
onFulfilled
默认是 透传值:value => value
(值穿透)
onRejected
默认是 抛出错误:error => { throw error }
(错误继续向下传)
// then 方法
then(onFulfilled, onRejected) {
// 处理参数可选性
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };
实现链式调用:返回 promise2。
// 实现链式调用
let promise2 = new MyPromise((resolve, reject) => {
const handleCallback = (callback, value) => {
setTimeout(() => {
try {
let x = callback(value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.state === 'fulfilled') {
handleCallback(onFulfilled, this.value);
} else if (this.state === 'rejected') {
handleCallback(onRejected, this.reason);
} else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => handleCallback(onFulfilled, this.value));
this.onRejectedCallbacks.push(() => handleCallback(onRejected, this.reason));
}
});
return promise2
}
单独对传入的形参 executor
进行分析。
handleCallback
函数是一个内部辅助函数,用来统一处理回调执行。
这里的callback
又是函数形参,以后放用户传给.then()
的函数如 onFulfilled
或 onRejected
。
value 中传上一个Promise的成功值或失败原因。
(resolve, reject) => {
const handleCallback = (callback, value) => {
// 异步执行
setTimeout(() => {
try {
let x = callback(value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
这里讲述一下resolvePromise
的作用:根据 x 的类型决定如何设置 promise2 的状态。
如果 x 是普通值 → resolve(x)
如果 x 是 Promise → promise2 跟随它的状态
对于跟随状态的解释:
运动员 A(promise1)跑完 → 把接力棒交给 B
运动员 B(promise2)拿到棒 → 开始跑
B 的成绩取决于他自己的表现,而不是 A 的
如果 x 是 thenable → 调用它的 .then() 并等待
如果 x === promise2 → 循环引用,报错
如果 x 是对象且有 .then 方法 → 当作 thenable 处理
如果当前Promise已经成功,立即异步执行成功回调并传入成功值。
失败传原因balabalabala…
如果还没有执行,把这个回调函数放入等待队列,最开始创建的队列。
if (this.state === 'fulfilled') {
handleCallback(onFulfilled, this.value);
} else if (this.state === 'rejected') {
handleCallback(onRejected, this.reason);
} else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => handleCallback(onFulfilled, this.value));
this.onRejectedCallbacks.push(() => handleCallback(onRejected, this.reason));
}
});
每一个.then()
返回的promise2
都在等待前一个异步操作完成。
接下来实现catch
函数,它只处理失败情况。
采取的措施是,一直传递失败。
catch(onRejected) {
return this.then(null, onRejected);
}
然后实现finally
函数,不管成功还是失败,都要执行它。成功传值,失败传错误。
finally(onFinally) {
return this.then(
value => MyPromise.resolve(onFinally()).then(() => value),
reason => MyPromise.resolve(onFinally().then(() => { throw reason; })
));
}
static resolve
用来返回一个已成功的Promise
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
static reject
用来创建一个已失败的Promise
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
等待所有 Promise 完成,如果都成功,返回结果数组;只要有一个失败,就立即失败。
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let remaining = promises.length;
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
remaining--;
if (remaining == 0) {
resolve(results);
}
},
reason => reject(reason)
);
});
});
}
只要有一个 Promise 完成(成功或失败),就采用它的结果。
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
同一个类中,写了const resolve又写了static resolve,它们之间没有冲突。虽然名字都是 resolve,但它们存在于完全不同的作用域和上下文中,不会互相干扰。reject同理。
在race和all中,直接调用了static resolve(value);
而reject部分使用的是当前实例的reject函数。