手写 Promise:深入理解异步编程
手写 Promise:深入理解异步编程
在现代 JavaScript 中,Promise 是一种用于处理异步操作的重要工具。通过手写实现一个简单的 Promise 类,我们能更深入地理解 Promise 的工作原理和异步编程的机制。在这篇博客中,我们将逐步构建一个功能齐全的 Promise 类,包括基本结构、then
方法、静态方法如 resolve
、reject
、all
、allSettled
、race
和 any
,以及一些辅助方法。
Promise 的基本结构
首先,我们定义一个 MyPromise
类,其中包含常见的 Promise 状态和基本结构:
class MyPromise {
static REJECTED = 'rejected';
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
value = undefined;
status = MyPromise.PENDING;
onFulfilledCallBacks = [];
onRejectedCallBacks = [];
constructor(execute) {
const resolve = (value) => {
if (this.status === MyPromise.PENDING) {
this.value = value;
this.status = MyPromise.FULFILLED;
this.onFulfilledCallBacks.forEach((func) => func(value));
}
};
const reject = (value) => {
if (this.status === MyPromise.PENDING) {
this.value = value;
this.status = MyPromise.REJECTED;
this.onRejectedCallBacks.forEach((func) => func(value));
}
};
try {
execute(resolve, reject);
} catch (error) {
reject(error);
}
}
// ...(后续实现)
}
这里定义了 MyPromise
类的基本结构,包括状态常量、初始值、状态和执行回调数组等。
实现 then
方法
then
方法是 Promise 的核心,它用于注册在 Promise 完成时执行的回调函数。以下是 then
方法的基本实现:
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (onFulfilled) => onFulfilled;
onRejected = typeof onRejected === 'function' ? onRejected : (onRejected) => onRejected;
return new MyPromise((resolve, reject) => {
// 处理已完成状态
if (this.status === MyPromise.FULFILLED) {
try {
queueMicrotask(() => {
const result = onFulfilled(this.value);
this.handlePromiseResult(result, resolve, reject);
});
} catch (error) {
reject(error);
}
}
// 处理已拒绝状态
else if (this.status === MyPromise.REJECTED) {
try {
queueMicrotask(() => {
const result = onRejected(this.value);
this.handlePromiseResult(result, resolve, reject);
});
} catch (error) {
reject(error);
}
}
// 处理异步状态
else {
this.onFulfilledCallBacks.push((value) => {
queueMicrotask(() => {
const result = onFulfilled(value);
this.handlePromiseResult(result, resolve, reject);
});
});
this.onRejectedCallBacks.push((value) => {
queueMicrotask(() => {
const result = onRejected(value);
this.handlePromiseResult(result, resolve, reject);
});
});
}
});
}
handlePromiseResult(result, resolve, reject) {
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
}
在 then
方法中,我们判断当前 Promise 的状态,根据状态的不同执行相应的回调函数。如果是异步状态,则将回调函数推入对应的回调数组中,等待状态改变时执行。
实现 resolve
和 reject
静态方法
resolve
和 reject
是 MyPromise
类的两个静态方法,用于创建已解决或已拒绝的 Promise。以下是它们的实现:
static resolve = (value) => {
return new MyPromise((resolve, reject) => {
resolve(value);
});
};
static reject = (value) => {
return new MyPromise((resolve, reject) => {
reject(value);
});
};
这两个方法分别返回一个已解决或已拒绝的 Promise。
实
现 all
方法
all
方法接收一个 Promise 数组,返回一个新的 Promise。只有当所有输入的 Promise 都解决时,新 Promise 才会解决,并返回包含所有 Promise 结果的数组;否则,只要有一个 Promise 拒绝,新 Promise 就会被拒绝。
static all = (promises) => {
if (!this._hasIterator(promises)) {
throw new Error('参数不可迭代');
}
return new MyPromise((resolve, reject) => {
const resultArr = [];
promises.forEach((promise) => {
promise.then(
(res) => {
if (resultArr.length === promises.length) {
resolve(resultArr);
}
resultArr.push(res);
},
(err) => {
reject(err);
}
);
});
});
};
实现 allSettled
、race
和 any
方法
allSettled
方法返回一个 Promise,该 Promise 在所有给定的 Promise 都已经解决或拒绝后解决。它会等待所有的 Promise 完成,无论成功还是失败,并返回一个包含每个 Promise 结果的数组。
static allSettled = (promises) => {
if (!this._hasIterator(promises)) {
throw new Error('参数不可迭代');
}
return new MyPromise((resolve) => {
const resultArr = [];
promises.forEach((promise, index) => {
promise.then(
(res) => {
resultArr.push({ status: 'fulfilled', value: res });
if (resultArr.length === promises.length) {
resolve(resultArr);
}
},
(res) => {
resultArr.push({ status: 'rejected', reason: res });
if (resultArr.length === promises.length) {
resolve(resultArr);
}
}
);
});
});
};
race
方法返回一个 Promise,该 Promise 在给定的任意 Promise 解决或拒绝后立即解决。
static race = (promises) => {
if (!this._hasIterator(promises)) {
throw new Error('参数不可迭代');
}
return new MyPromise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(
(res) => {
resolve(res);
},
(res) => {
reject(res);
}
);
});
});
};
any
方法返回一个 Promise,该 Promise 在给定的任意 Promise 解决后立即解决。与 race
不同的是,any
只要有一个 Promise 解决即可,不管其状态是成功还是失败。
static any = (promises) => {
if (!this._hasIterator(promises)) {
throw new Error('参数不可迭代');
}
return new MyPromise((resolve, reject) => {
promises.forEach((promise) => {
promise.then((res) => {
resolve(res);
});
});
});
};
辅助方法:deferred
为了方便创建一个延迟解决的 Promise 对象,我们添加了 deferred
方法:
static deferred = () => {
let dfd = {};
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
这个方法返回一个包含 promise
、resolve
和 reject
的对象,方便后续使用。
总结
通过以上的实现,我们成功地创建了一个简单但功能齐全的 Promise 类。这个手写 Promise 不仅具备基本的异步操作能力,还支持 Promise 链式调用和常见的 Promise 方法,如 then
、resolve
、reject
、all
、allSettled
、race
和 any
。
手写实现 Promise 是一个有挑战性但也有益处的练习,有助于更深入地理解 Promise 的工作原理和异步编程的机制。希望这篇博客对你理解 Promise 有所帮助。
转载自:https://juejin.cn/post/7339042131467616296