自己实现一个Promise
最近看到好多讲解Promise源码解析,或者自己实现一个Promise的文章,突然想自己造个轮子试一试。
先说明一下,该轮子并不完全遵守任何标准和规范,只是对正规Promise使用后的理解和感受而编写的,纯属兴趣研究。
下面是实现代码:
// 对象类型判断 const is = (typeAsString) => obj => Object.prototype.toString.call(obj) === typeAsString // 判断是否为一个Error对象 const isError = is('[object Error]') /** * 自定义Promise对象 * @param {(resolve: (value: any) => void, reject: (reason: any) => void) => void} executor */ function MyPromise(executor) { this.executor = executor // 初始状态为pending... this.status = 'pending' /** * 内部判定状态,只有处于pending状态才可继续执行 * @param {number} value */ function resolve(value) { if (this.status === 'pending') { // 确保只执行一次 this.onfulfilled = ___onfulfilled.call(this, value) } } /** * 为了缓存resolve方法的执行结果 * @param {*} value value就是resolve方法的执行结果 */ function ___onfulfilled(value) { this.status = 'fulfilled' // 更改内部状态 /** * @param {(value: number) => void} onfulfilled 这里是then方法中传入的参数 */ return (onfulfilled) => { return onfulfilled(value) // } } /** * 触发异常的方法 * @param {string} reason */ function reject(reason) { if (this.status === 'pending') { // 确保只执行一次 this.onrejected = ___onrejected.call(this, reason) } } /** * * @param {Error} reason 如果传入的不是一个Error对象,那么会使用Error包装一下 */ function ___onrejected(reason) { this.status = 'rejected' // 更改内部状态 return (onrejected) => { reason = isError(reason) ? reason : new Error(reason) return onrejected(reason) } } /** * @param {(value: number) => any} onfulfilled 处理成功的函数 * @param {(reason: any) => void} onrejected 处理出现异常的函数,如果传入该参数,那么catch方法就捕获不到了 */ this.then = function(onfulfilled, onrejected) { const self = this return new MyPromise((resolve, reject) => { setTimeout(function waitStatus() { switch (self.status){ case 'fulfilled': // resolved if (onfulfilled) { // 将onfulfilled方法的返回值交给resolve,确保下一个.then方法能够得到上一个.then方法的返回值 const nextValue = self.onfulfilled(onfulfilled) resolve(nextValue) } else { resolve() // 没有传入参数,假装传入了参数:) } break case 'rejected': // rejected if (!onrejected) { // 如果没有传递onrejected参数,默认实现一个,确保catch方法能够捕获到 onrejected = (reason) => reason } const nextReject = self.onrejected(onrejected) reject(nextReject) break case 'pending': // default: setTimeout(waitStatus, 0) // 只要是pending状态,继续等待,直到不是pending break } }, 0); }) } /** * 捕获异常 * @param {(reason: any) => void} onrejected */ this.catch = function(onrejected) { const self = this setTimeout(function reject() { if (self.status === 'rejected') { self.onrejected(onrejected) } else { setTimeout(reject, 0); } }, 0); } // 直接执行 this.executor(resolve.bind(this), reject.bind(this)); }
目前不考虑参数传入的正确性,假设传入的参数全部是正确的情况下,在nodejs环境下能够正常运行。以下是测试代码:
// 覆盖nodejs环境中默认的Promise对象 global.Promise = MyPromise async function test () { const r = await new Promise((resolve) => { setTimeout(() => { resolve(121) }, 1000); }) console.log(r) // 打印121 } test()
以上代码主要是使用setTimeout方法去检查Promise对象内部的状态,一旦发生变化立即作出相应的处理。
因为是靠setTimeout方法检查Promise内部的状态,所以属于宏指令任务,执行的优先级不像正规Promise那么高。
setTimeout(() => { console.log(1) }, 0); new MyPromise((resolve, reject) => { console.log(2) resolve(3) }).then(v => { console.log(v) })
上面代码的输出是2,1,3
正规Promise的输出结果应该是2,3,1
源代码在此。谢谢观看!
相关推荐
nmgxzm00 2020-11-10
xixixi 2020-11-11
88254251 2020-11-01
MarukoMa 2020-09-02
88234852 2020-09-15
陈旭阳 2020-08-31
whynotgonow 2020-08-19
前端开发Kingcean 2020-07-30
whynotgonow 2020-07-29
bowean 2020-07-08
前端开发Kingcean 2020-07-08
88520191 2020-07-05
前端开发Kingcean 2020-06-27
88481456 2020-06-18
whynotgonow 2020-06-16
88520191 2020-06-13
88520191 2020-06-13
89500297 2020-06-13