Node.js中使用await后数组push操作后数组为空问题求助
问题描述
尝试遍历数组,从数据库获取每支股票的数量和价格,计算后将结果推入数组。但执行const db_stock = await Stocks.findById(stock.stockId);这个数据库查询并push后,数组始终为空。移除该代码后功能正常,加回await后数组又变为空。相关代码如下:
import mongoose from "mongoose"; import { response } from "express"; import StockDispatches from "../models/StockDispatch.js" import Stocks from "../models/Stocks.js" import { createError } from "../error.js"; import validator from 'express-validator' const { validationResult } = validator import { generateRamdom } from "../utils/Utils.js" export const createStockDispatched = async (req, res, next) => { const error = validationResult(req).formatWith(({ msg }) => msg); const trx_id = generateRamdom(30); let quantity = 0; let total = 0; let dispatchedTotal = 0; const hasError = !error.isEmpty(); if (hasError) { res.status(422).json({ error: error.array() }); } else { const options={ordered: true}; let user_stocks =[]; req.body.stocks.map(async (stock, index) => { let total = stock.price * stock.quantity const db_stock = await Stocks.findById(stock.stockId); if(!db_stock) return res.status(404).json({msg: "Stock Not Found."}) if( stock.quantity > db_stock.quantity) return res.status(208).json({msg: `Quantity of ${stock.name} is greater than what we have in database`}) quantity = db_stock.quantity - stock.quantity; total = quantity * db_stock.price; const updated_stock = await Stocks.findByIdAndUpdate(stock.id, {quantity, total},{$new: true}) dispatchedTotal = stock.quantity * db_stock.price; user_stocks.push("samson") user_stocks.push({...stock, staffId: req.user.id, total: dispatchedTotal, trx_id, stockId: stock.id, price: db_stock.price}) }); try{ const stockDispatched = await StockDispatches.insertMany(user_stocks, options); if(!stockDispatched) return res.status(500).json({msg: "Error. Please try again."}) return res.status(200).json({msg: "Stock uploaded successfully.."}) }catch(error){ next(error) } } }
问题原因
map与async/await不兼容:map函数会直接返回一个Promise数组,但代码中没有等待这些Promise执行完成,就立刻执行了StockDispatches.insertMany(user_stocks, options)。此时user_stocks还没被填充任何数据,自然为空。- 错误的响应方式:在
map的异步回调里直接return res.status(...).json(...),可能会导致多次响应同一个请求,引发错误。
解决方案
将map替换为for...of循环,它能和await完美配合,确保每一步异步操作完成后再继续执行,同时统一处理错误响应:
import mongoose from "mongoose"; import { response } from "express"; import StockDispatches from "../models/StockDispatch.js" import Stocks from "../models/Stocks.js" import { createError } from "../error.js"; import validator from 'express-validator' const { validationResult } = validator import { generateRamdom } from "../utils/Utils.js" export const createStockDispatched = async (req, res, next) => { const error = validationResult(req).formatWith(({ msg }) => msg); const trx_id = generateRamdom(30); let quantity = 0; let total = 0; let dispatchedTotal = 0; const hasError = !error.isEmpty(); if (hasError) { return res.status(422).json({ error: error.array() }); } try { const options = { ordered: true }; let user_stocks = []; // 用for...of替代map,确保await执行完成后再推进数组 for (const stock of req.body.stocks) { const db_stock = await Stocks.findById(stock.stockId); if (!db_stock) { return res.status(404).json({ msg: "Stock Not Found." }); } if (stock.quantity > db_stock.quantity) { return res.status(208).json({ msg: `Quantity of ${stock.name} is greater than what we have in database` }); } quantity = db_stock.quantity - stock.quantity; total = quantity * db_stock.price; // 修正参数:用stock.stockId匹配数据库中的股票ID await Stocks.findByIdAndUpdate(stock.stockId, { quantity, total }, { new: true }); dispatchedTotal = stock.quantity * db_stock.price; user_stocks.push("samson"); user_stocks.push({ ...stock, staffId: req.user.id, total: dispatchedTotal, trx_id, stockId: stock.stockId, price: db_stock.price }); } const stockDispatched = await StockDispatches.insertMany(user_stocks, options); if (!stockDispatched) { return res.status(500).json({ msg: "Error. Please try again." }); } return res.status(200).json({ msg: "Stock uploaded successfully.." }); } catch (error) { next(error); } }
额外说明
- 原代码中
Stocks.findByIdAndUpdate(stock.id, ...)存在参数错误,应该使用stock.stockId匹配数据库中的股票ID,已在解决方案中修正。 - 使用
for...of可以保证异步操作的顺序执行,避免并发修改导致的逻辑错误。
内容的提问来源于stack exchange,提问作者etranz
相关产品推荐
相关产品推荐

