JavaScript手写Promise链式调用出现Cannot read property 'then' of undefined错误原因
问题原因分析
报错的直接原因是then方法没有返回新创建的MyPromise实例:你在then方法内部创建了用于链式传递的promise对象,但方法执行结束没有把这个实例返回,导致第一次调用then后返回值为undefined,再链式调用.then()自然会抛出Cannot read property 'then' of undefined的错误。
除此之外你的自定义Promise还存在多处逻辑缺陷,修复后才能正常运行:
- 构造函数的异常捕获逻辑错误:catch块中只对
onReject做了绑定没有执行,也没有传入捕获到的异常参数 - 实例类型判断逻辑错误:用
typeof result === 'MyPromise'判断实例是无效的,typeof判断对象只会返回object,应该用instanceof关键字 - 拒绝状态取值错误:
propageRejected方法中调用catch函数时传入的是this.value,应该传入存储拒绝原因的this.error - 缺省回调的透传逻辑缺失:如果then方法没有传入对应状态的回调函数,需要把值/错误直接透传给下一个Promise实例
核心代码修复示例
修复then方法的返回逻辑
then = (fullfilledFn, catchFn) => { const promise = new MyPromise(); this.thenQueue.push([promise, fullfilledFn, catchFn]); if(this.state === states.FULFILLED) { this.propageFulFilled() } else if(this.state == states.REJECTED) { this.propageRejected(); } // 新增返回promise实例,支持链式调用 return promise; }
修复构造函数的异常捕获逻辑
setTimeout(() => { try { computation( this.onFulFilled.bind(this), this.onReject.bind(this) ); } catch(ex) { // 直接执行onReject传入异常 this.onReject(ex); } });
修复完成状态的传播逻辑
propageFulFilled = () => { for(const [promise, fullFilledFn] of this.thenQueue) { // 缺省回调直接透传值 if (typeof fullFilledFn !== 'function') { promise.onFulFilled(this.value); continue; } const result = fullFilledFn(this.value); // 改用instanceof判断实例类型 if(result instanceof MyPromise) { result.then( value => promise.onFulFilled(value), error => promise.onReject(error) ) } else { promise.onFulFilled(result); } } this.thenQueue = []; }
修复拒绝状态的传播逻辑
propageRejected = () => { for(const [promise, _, catchFn] of this.thenQueue) { // 缺省错误回调直接透传错误 if (typeof catchFn !== 'function') { promise.onReject(this.error); continue; } const result = catchFn(this.error); if(result instanceof MyPromise) { result.then( value => promise.onFulFilled(value), error => promise.onReject(error) ) } else { promise.onFulFilled(result); } } this.thenQueue = []; }
内容的提问来源于stack exchange,提问作者myTest532 myTest532
相关产品推荐
相关产品推荐

