Graphql+Nodejs报错:Cannot read property 'forEach' of undefined求助
排查TypeError: Cannot read property 'forEach' of undefined错误
这个报错指向很明确——你尝试对一个undefined值调用forEach方法,具体来说就是代码里的input.pedido是undefined,导致无法执行遍历操作。下面我帮你拆解问题原因和解决办法:
错误原因
你的代码直接默认input.pedido一定是一个数组,但实际场景中很容易出现以下情况:
- 客户端发起请求时,完全没有传递
pedido字段 - 传递的
pedido字段值不是数组(比如是null、字符串或者其他非数组类型)
这两种情况都会让input.pedido变成undefined或者非数组,进而触发Cannot read property 'forEach' of undefined的错误。
另外还要提一下你代码里的两个隐性问题:
- Promise的回调参数写错了,第二个参数应该是
reject而不是object newPedido.save里的rejects是拼写错误,正确应该是reject- 当前代码里的
updateOne是异步操作,但你没有等待所有更新完成就执行save,可能导致库存还没更新,订单就已经保存了,出现数据不一致的问题
解决方法
1. 先校验input.pedido的合法性
在调用forEach之前,先检查input.pedido是否存在且是数组,如果不满足条件,直接返回错误提示。
2. 修复异步操作的顺序问题
用Promise.all等待所有库存更新操作完成后,再执行订单保存,保证数据一致性;同时修正拼写和参数错误。
修正后的代码
newPedido: (root, { input }) => { // 先校验input.pedido是否为有效数组 if (!input.pedido || !Array.isArray(input.pedido)) { return Promise.reject(new Error("pedido字段必须是一个非空数组")); } const newPedido = new Pedidos({ pedido: input.pedido, total: input.total, fecha: new Date(), cliente: input.cliente, estado: "PENDIENTE" }); newPedido.id = newPedido._id; return new Promise((resolve, reject) => { // 把所有updateOne操作包装成Promise,用Promise.all等待全部完成 const updatePromises = input.pedido.map(pedido => { return Productos.updateOne( { _id: pedido.id }, { "$inc": { "stock": -pedido.cantidad } } ).catch(error => { // 捕获单个库存更新的错误 throw new Error(`更新商品库存失败: ${error.message}`); }); }); Promise.all(updatePromises) .then(() => { // 所有库存更新完成后,再保存订单 newPedido.save((error) => { if (error) reject(error); else resolve(newPedido); }); }) .catch(updateError => { // 处理库存更新的错误 reject(updateError); }); }); }
额外优化建议
- 可以在GraphQL的Schema里定义
pedido为非空数组类型,从请求入口就避免客户端传递无效值 - 改用
async/await语法,让异步代码更易读和维护,示例如下:
newPedido: async (root, { input }) => { if (!input.pedido || !Array.isArray(input.pedido)) { throw new Error("pedido字段必须是一个非空数组"); } const newPedido = new Pedidos({ pedido: input.pedido, total: input.total, fecha: new Date(), cliente: input.cliente, estado: "PENDIENTE" }); newPedido.id = newPedido._id; try { // 等待所有库存更新完成 await Promise.all(input.pedido.map(pedido => Productos.updateOne( { _id: pedido.id }, { "$inc": { "stock": -pedido.cantidad } } ) )); // 保存订单 await newPedido.save(); return newPedido; } catch (error) { throw new Error(`创建订单失败: ${error.message}`); } }
内容的提问来源于stack exchange,提问作者JOSE JOLLJA
相关产品推荐
相关产品推荐

