Node控制器中await Promise报不可迭代错误的原因及解决方法
问题根因
- 直接触发报错的问题:
Promise.all()的入参必须是可迭代对象(最常见的是Promise实例组成的数组),代码中直接传入单个Promise实例,单个Promise没有实现Symbol.iterator迭代接口,因此抛出object is not iterable的类型错误。 - 逻辑缺陷1:自定义的Promise实例没有调用
resolve()或reject()改变状态,就算解决了入参错误,await会一直处于挂起状态,永远不会执行后续逻辑。另外给Promise的executor函数加async关键字没有实际意义,executor本身就会被Promise立即同步执行,加async只会额外生成一层冗余Promise包装,还会导致executor内部的同步报错无法被Promise正常捕获。 - 逻辑缺陷2:代码块内的字段更新逻辑全是同步操作,同步代码本身就是按顺序逐行执行的,执行完成后才会运行后续代码,完全不需要额外包装Promise,属于冗余设计。
修正方式
如果当前逻辑都是同步代码,直接移除多余的Promise包装即可,代码会自动按顺序执行:
updatedFields.last_login_at = newDateNow(); if (updatedFields.isActivated) { updatedFields.activated_at = newDateNow(); updatedFields.deactivated_at = null; } else if (updatedFields.isActivated === false) { updatedFields.deactivated_at = newDateNow(); updatedFields.activated_at = null; } // 直接写后续逻辑即可,前面的同步代码执行完成后才会走到这里
如果后续要在这段逻辑里加入异步操作、确实需要Promise包装,直接await单个Promise即可,不需要调用Promise.all(),同时要正确处理Promise状态变更:
const other = new Promise(function (resolve, reject) { try { updatedFields.last_login_at = newDateNow(); if (updatedFields.isActivated) { updatedFields.activated_at = newDateNow(); updatedFields.deactivated_at = null; } else if (updatedFields.isActivated === false) { updatedFields.deactivated_at = newDateNow(); updatedFields.activated_at = null; } // 逻辑执行完成必须调用resolve标记Promise结束 resolve(); } catch (err) { // 捕获错误通过reject抛出 reject(err); } }); // 单个Promise直接await即可 await other; // 后续剩余代码
内容的提问来源于stack exchange,提问作者Zoe
相关产品推荐
相关产品推荐

