手写实现 Promise/A+ 标准
本文仅作为个人记录,文中可能存在不严谨的地方。
Promise/A+ 的标准有哪些?
- 只有一个
then
方法,没有catch
、race
、all
等方法。 then
返回一个新的 Promise。- 不同的 Promise 的实现需要相互调用。
- Promise 的状态有
pending
、fullfilled
、rejected
三种。初始状态是pending
,可以由pending
转化为fullfilled
或者rejected
。一旦状态确定之后,不能再被改变。 - 更具体的官方标准,看这里。
具体代码实现
function MyPromise(executor) { const _this = this // 状态 _this.status = 'pending' // resolve 值 _this.value = null // reject 原因 _this.reason = null // resolve、reject 函数 _this.onFullfilled = [] _this.onRejected = [] function resolve(value) { if (value instanceof MyPromise) { return value.then(resolve, reject) } // 其实这里采用 setTimeout 方式实现异步执行 onFullfilled/onRejected 不太符合 Event Loop 机制。下面 reject 同理。 setTimeout(() => { // 只有状态为 pending 才能被改变 if (_this.status == 'pending') { _this.value = value _this.status = 'resolved' _this.onFullfilled.forEach(currentValue => currentValue(value)) } }, 0) } function reject(reason) { setTimeout(() => { // 只有状态为 pending 才能被改变 if (_this.status == 'pending') { _this.reason = reason _this.status = 'rejected' _this.onRejected.forEach(currentValue => currentValue(reason)) } }, 0) } // 注意:若执行过程出现异常,则捕获异常并执行 reject 函数。 try { executor(resolve, reject) } catch (e) { reject(e) } } function resolvePromise(promise2, x, resolve, reject) { let then let thenCallorThrow = false if (promise2 === x) { return reject(new TypeError('same Promise!')) } if (x instanceof MyPromise) { if (x.status === 'pending') { x.then(value => { resolvePromise(promise2, value, resolve, reject) }, reject) } else { x.then(resolve, reject) } return } if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { then = x.then if (typeof then === 'function') { then.call( x, res => { if (thenCallorThrow) return thenCallorThrow = true return resolvePromise(promise2, res, resolve, reject) }, err => { if (thenCallorThrow) return thenCallorThrow = true return reject(err) } ) } else { resolve(x) } } catch (e) { if (thenCallorThrow) return thenCallorThrow = true return reject(e) } } else { return resolve(x) } } MyPromise.prototype.then = function (onFullfilled, onRejected) { const _this = this let promise2 // promise.then() 返回一个 promise 对象 // Promise 值的穿透处理: // 场景如: new Promise(resolve => resolve('abc')).then().catch().then(res => {console.log('print abc')}) onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : val => val onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err } switch (_this.status) { case 'pending': promise2 = new MyPromise((resolve, reject) => { _this.onFullfilled.push(value => { try { const x = onFullfilled(value) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) _this.onRejected.push(reason => { try { const x = onRejected(reason) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) }) break case 'resolved': promise2 = new MyPromise((resolve, reject) => { setTimeout(() => { try { const x = onFullfilled(_this.value) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) }) break case 'rejected': promise2 = new MyPromise((resolve, reject) => { setTimeout(() => { try { const x = onRejected(_this.reason) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) }) break default: break } return promise2 } // Promise 标准里面没有 catch、race、all 等方法,只有一个 then 方法 MyPromise.prototype.catch = function (onRejected) { return this.then(null, onRejected) } new MyPromise((resolve, reject) => { resolve('right') }).then( res => { console.log(res) }, err => { console.warn(err) } )
要了解更多可以看下这两篇文章:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论