手动实现Promise类
Promise 是 JavaScript 中用于处理异步操作的对象,我们可以手写实现一个符合 Promise A+ 规范的 Promise。
首先需要理解 Promise 的基本结构和功能。Promise 对象包含三种状态:pending
(等待中)、fulfilled
(已成功)和 rejected
(已失败)。当 Promise 转换到 fulfilled 或 rejected 状态时,会把结果值或错误原因传递给 then 方法注册的回调函数。
以下是一个简单的 Promise 实现:
class CustomPromise {
constructor(executor) {
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((callback) => callback(value));
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(reason));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new CustomPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
try {
const value =
typeof onFulfilled === 'function' ? onFulfilled(this.value) : this.value;
resolve(value);
} catch (error) {
reject(error);
}
} else if (this.state === 'rejected') {
try {
const reason =
typeof onRejected === 'function' ? onRejected(this.reason) : this.reason;
reject(reason);
} catch (error) {
reject(error);
}
} else {
this.onFulfilledCallbacks.push((value) => {
try {
const returnValue =
typeof onFulfilled === 'function' ? onFulfilled(value) : value;
resolve(returnValue);
} catch (error) {
reject(error);
}
});
this.onRejectedCallbacks.push((reason) => {
try {
const returnValue =
typeof onRejected === 'function' ? onRejected(reason) : reason;
reject(returnValue);
} catch (error) {
reject(error);
}
});
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(onFinally) {
return this.then(
(value) =>
CustomPromise.resolve(onFinally()).then(() => {
return value;
}),
(reason) =>
CustomPromise.resolve(onFinally()).then(() => {
throw reason;
})
);
}
static resolve(value) {
return new CustomPromise((resolve) => resolve(value));
}
static reject(reason) {
return new CustomPromise((resolve, reject) => reject(reason));
}
static all(promises) {
return new CustomPromise((resolve, reject) => {
const results = Array(promises.length);
let count = 0;
promises.forEach((promise, index) => {
CustomPromise.resolve(promise).then(
(value) => {
results[index] = value;
count++;
if (count === promises.length) {
resolve(results);
}
},
(reason) => {
reject(reason);
}
);
});
});
}
static race(promises) {
return new CustomPromise((resolve, reject) => {
promises.forEach((promise) => {
CustomPromise.resolve(promise).then(resolve, reject);
});
});
}
}
这个实现中用到了构造函数、then 方法、catch 方法、finally 方法和静态方法 resolve、reject、all 和 race。在构造函数中,通过传入一个 executor 函数,创建了一个新的 CustomPromise 对象,并且在 executor 函数中调用 resolve 或 reject 来改变 CustomPromise 的状态;在 then 方法中,通过不同状态下返回值的处理,实现了链式调用。
需要注意的是,在实现中使用了数组来保存每个回调函数,因为 Promise 可能会存在多个 then 方法,当状态改变时需要执行所有的回调函数,而保存回调函数的数组也是实现 Promise 链式调用的关键。
此外,这个实现还加入了 catch 和 finally 方法,用于捕获 Promise 的错误和添加无论 Promise 状态如何都会执行的逻辑。
使用CustomPromise
首先可以创建一个新的 CustomPromise 对象,传入一个 executor 函数。executor 函数接受两个参数:resolve 和 reject,分别代表成功和失败的回调函数。当异步操作成功时,调用 resolve 方法并传入成功结果值;当异步操作失败时,调用 reject 方法并传入错误原因。
然后就可以在 CustomPromise 实例上调用 then 方法来注册处理 Promise 成功和失败的回调函数。then 方法接受两个参数:onFulfilled 和 onRejected,分别代表成功和失败的回调函数。这些回调函数会在 Promise 转换到 fulfilled 或 rejected 状态时被调用,并且会把结果值或错误原因传递给它们。
除了 then 方法,CustomPromise 类还提供了 catch 方法用于捕获 Promise 的错误,以及 finally 方法用于添加无论 Promise 状态如何都会执行的逻辑。
以下是使用 CustomPromise 处理异步操作的示例代码:
const customPromise = new CustomPromise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const randomNum = Math.random();
if (randomNum > 0.5) {
resolve('success');
} else {
reject('failed');
}
}, 1000);
});
customPromise.then(
(value) => {
console.log(value);
},
(reason) => {
console.log(reason);
}
);
customPromise.catch((error) => {
console.log(error);
});
customPromise.finally(() => {
console.log('finally');
});
在这个示例中,我们创建了一个 CustomPromise 对象来模拟异步操作。在 executor 函数中使用 setTimeout 模拟异步操作,并根据随机生成的数值来改变 CustomPromise 的状态。然后调用 then 方法、catch 方法和 finally 方法来注册处理 Promise 成功和失败的回调函数以及添加执行无论 Promise 状态如何都会执行的逻辑。