废了1-2天功夫编写了一套能实现异步Promise的构造函数,实现以下功能:
(1)通过newPromise((res,rej)=>{})构造一个Promise功能的方法
(2)通过then获取onFulfilled或者onRejected状态返回的值
(3)通过catch捕获之前rejected的错误
/*promise状态,PENDING阻塞、FULFILLED完成、REJECTED失败*/const PENDING = 0, FULFILLED = 1, REJECTED = 2;/*then中需要返回一个新的promise,promise初始化用的resolver*/function noop() {};/*resolver必须为一个方法,不是给出typeError提示*/function needsResolver() { throw new TypeError('You must pass a resolver function as the first argument to the promise constructor')}/*Promise构造函数生成,不是给出typeError提示*/function needsNew() { throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}class newPromise { constructor(resolver) { /*当前Promise状态*/ this.PromiseStatus = PENDING /*final执行时需要的标记,防止乱序执行*/ this._deferredState = 0 //1在进行final 否则不在 /*存放的后续then执行的({onFulfilled,onRejected})方法*/ this._deferreds = [] /*保存当前值,可以是resolve或者reject返回的值*/ this.PromiseValue = null /*resolver是否是方法,不是提示报错信息*/ typeof resolver !== 'function' && needsResolver(); this instanceof newPromise ? init_(this, resolver) : needsNew(); }}newPromise.prototype.then = then_newPromise.prototype.catch = catch_function init_(promise, resolver) { try { resolver((val) => { resolve_(promise, val) }, (err) => { reject_(promise, err) }) } catch (e) { catch_(e) }}/*与then相似,只是没有onFulfilled参数*/function catch_(onRejected) { var promise = new newPromise(noop); let handler = new Handler(this, null, onRejected, promise) pushTo_(this, handler) return promise;}/*reject,resolve之后会调用*/function final_(promise) { if (promise._deferreds.length > 0) {//将结果返回 if (promise._deferredState === 1) return promise._deferredState = 1 let defer = promise._deferreds[0] handle_(promise, defer); }}function pushTo_(promise, deferred) { promise._deferreds.push(deferred)}function handle_(self, defer) {//{defer 是一个对象,有三个参数:onFulfilled,onRejected,promise var cb = self.PromiseStatus === FULFILLED ? defer.onFulfilled : defer.onRejected; if (cb === null) { /*状态不变,再次调用then才将PromiseValue输出*/ self._deferreds.pop() if (self.PromiseStatus === FULFILLED) { resolve_(self, self.PromiseValue) } else { reject_(self, self.PromiseValue) } self._deferredState = 0 } else if (self.PromiseStatus === PENDING) { // if (self._deferredState === 0) { // self._deferredState = 1; // } } else { self._deferreds.pop() self._deferredState = 0 let promise = self.promise let callback = cb(self.PromiseValue) if (callback) { callback.then(res => { // console.log('---', callback) // if (callback.PromiseStatus === REJECTED) // reject_(promise, callback.PromiseValue) // else /*将callback返回值,在之前then生成的promise上发出,则promise.then可以捕获到,这样then就可以变成链式的了*/ resolve_(promise, callback.PromiseValue) }, rej => { reject_(promise, callback.PromiseValue) }) } }}//返回一个新的promisefunction then_(onFulfilled, onRejected) { var promise = new newPromise(noop); let handler = new Handler(this, onFulfilled, onRejected, promise) pushTo_(this, handler) return promise;}function resolve_(promise, val) { promise.PromiseStatus = FULFILLED promise.PromiseValue = val final_(promise)}function reject_(promise, err) { promise.PromiseStatus = REJECTED promise.PromiseValue = err final_(promise)}function Handler(promise, onFulfilled, onRejected, promise_) { promise.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; promise.onRejected = typeof onRejected === 'function' ? onRejected : null; promise.promise = promise_; return promise}复制代码
测试代码:
let newp = new newPromise((resolve, reject) => { setTimeout(() => { reject('1') })}).then(resolve => { console.log('resolve', resolve)}, reject => { console.log('reject:', reject) return new newPromise((resolve) => { setTimeout(() => { resolve('ok') }, 100) })}).then(res => { console.log('---res---', res) return new newPromise((resolve, reject) => { setTimeout(() => { reject('ok') }, 100) })}).then(res => { console.log('---res2---', res)}, rej => { console.log('---rej2---', rej) return new newPromise((resolve, reject) => { setTimeout(() => { reject('err') }, 100) })}).catch(err => { console.log(err)})复制代码
测试结果: