Promise 是一种异步编程解决方案,它提供了一种更加优美和便捷的方式来处理异步操作。下面是手写 Promise 的详细步骤和分析。
首先,我们需要了解 Promise 的三种状态:
当一个 Promise 被创建时,它的状态是 Pending。当 Promise 成功执行回调函数时,它的状态变成 Fulfilled。如果执行回调函数时发生了异常,Promise 的状态会变成 Rejected。
接下来,我们需要定义一个 Promise 构造函数,它需要一个执行器函数作为参数。执行器函数接受两个参数 resolve 和 reject,它们是两个函数,用于修改 Promise 的状态。
class MyPromise {
constructor(executor) {
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === 'pending') {
this.status = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.status = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
}
在构造函数中,我们定义了 Promise 的状态和值。onResolvedCallbacks 和 onRejectedCallbacks 数组用于存储 then 方法中传入的回调函数,当 Promise 的状态改变时,我们需要依次执行这些回调函数。
然后,我们需要定义 then 方法,它接受两个参数 onFulfilled 和 onRejected,它们分别是 Promise 成功和失败时的回调函数。
class MyPromise {
// ...
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === 'function'
? onRejected
: (reason) => {
throw reason;
};
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.status === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.status === 'pending') {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
}
在 then 方法中,我们首先需要判断 Promise 的状态。如果状态为 Fulfilled,直接调用 onFulfilled 回调函数,并且将返回值传入 resolvePromise 函数。resolvePromise 函数用于处理返回值,如果返回值为 Promise,则等待其状态改变后再传递结果。
如果状态为 Rejected,直接调用 onRejected 回调函数,并且将返回值传入 resolvePromise 函数。
如果状态为 Pending,将回调函数 push 到回调队列中。当 Promise 的状态改变时,依次执行这些回调函数,并在执行完成后,再调用 resolvePromise 函数。
在 resolvePromise 函数中,我们需要判断返回值的类型。如果为 Promise,则等待其状态改变后再传递结果。
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false;
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
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);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
在 resolvePromise 函数中,我们首先需要判断 x 和 promise2 是否相等,如果相等,说明出现了循环引用,需要抛出错误。
然后,我们需要判断 x 的类型。如果 x 是对象或函数,我们需要判断它是否有 then 方法。如果有 then 方法,则说明 x 是 Promise,需要等待其状态改变后再传递结果。否则,直接将 x 传递给 resolve 函数。
最后,我们需要在 Promise 类中定义 static 方法 resolve 和 reject,用于创建已经成功和失败的 Promise。
class MyPromise {
// ...
static resolve(value) {
if (value instanceof MyPromise) {
return value;
}
return new MyPromise((resolve) => resolve(value));
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
}
最终,我们得到了手写的 Promise 实现。