手写 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 有所帮助。