手写 Promise: 深入理解异步编程

程序员他爱做梦2024-05-30 11:31:53  114

手写 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://www.414w.com/read/626466.html
0
随机主题
米兰旧将: 德比六连败不可接受, 我在目前这支米兰能够踢上比赛史上成色最低的一场欧联决赛——看联赛排名, 冠军第5, 亚军第14不到10万的方盒子 混动油耗低 还有电四驱 BJ30上市导购一公里油耗才6毛钱 开瑞优劲 致富又带劲9.88万的自动挡合资SUV, 还配四轮独悬, 家用买它合适?丰田打响“价格战”, 合资B级车, 从近17万降至11万多, 20年也开不坏早安! 世界丨中方反制12家美国军工企业;联合国被迫暂停在拉法分发援助食品我们的广义货币, 为什么是美国的2倍?了解交法我有责 安全交通为大家12.58万起售, 长城炮2.4T柴油版来了, 提供6MT/9AT可选辛芷蕾实力和运气并存,玩套圈一次套中大奖,抽签直接欧皇附体三个“音符”奏响内部关系“和谐曲”美西方抢钱, 俄斗到底, 反制裁开始, 普京没收德最大银行在俄资产百年红会, 等你续写! “我与红会的故事”征文活动来了!体检报告送上门 真情服务暖人心拜登不满国际刑事法院,扎哈罗娃嘲讽:“陷入自己网中的蜘蛛”比亚迪皮卡详细参数曝光, 百公里油耗仅7.5L, 后排空间亮眼前总监: 拜仁结构混乱始于8000万签卢卡斯, 现队中太多高薪平庸者茅台的主营业务是什么? 你真的了解吗?谢晖死活不换人! 王禹李申圆跑拉胯了 贝里奇战犯级表现, 葛副总还是别上了传奇世界: 当年拥有这些武器就能称王称霸, 现在看不到了?
最新回复(0)