Node.js服务器崩溃求助:票务售罄时购票触发崩溃
问题根源分析
嘿,我帮你揪出了服务器崩溃的核心原因,咱们拆解来看:
- 你混合用了async/await和传统回调函数,但回调里抛出的错误根本进不了外层的
try/catch!比如Ticket.find()和ticket.save()里的throw new Error(),这些错误会变成「未捕获的异步异常」,直接把服务器干崩,而不是走你的错误处理逻辑。 Event.findById()同时用了await和回调,这既冗余又容易出问题,eventFound的赋值时机完全不可控,搞不好后续代码拿不到正确的活动数据。- 票数判断里用
event?.toJSON().maxTicketsAmount绕了弯路,而且没先确认活动是否存在,万一查不到活动,后续逻辑全乱。
修复后的完整代码
我把代码改成了纯async/await风格,所有错误都能被正确捕获处理,同时优化了逻辑:
try { const { email, firstName, lastName, phoneNumber } = req.body; const id = req.query.id; // 直接用await获取活动数据,移除冗余回调 const event = await Event.findById(id); if (!event) { throw new Error("活动不存在"); } // 用await获取已售票务,替代回调函数 const soldTickets = await Ticket.find({ eventId: event._id }); const remainingTickets = event.maxTicketsAmount - soldTickets.length; // 明确判断票务是否售罄 if (remainingTickets <= 0) { throw new Error("票务已售罄"); } // 创建Stripe支付意向(注意金额要转成最小单位,比如PLN要乘以100) const paymentIntent = await stripe.paymentIntents.create({ amount: event.ticketPrice * 100, // 重要:Stripe要求金额为最小单位整数,比如10PLN要传1000 currency: "pln", payment_method_types: ["card"], receipt_email: email, metadata: { integration_check: "accept a payment" }, }); console.log(paymentIntent); // 创建并保存新票务,用await确保错误能被捕获 const ticket = new Ticket({ email, firstName, lastName, phoneNumber, eventId: event._id, purchaseDate: new Date(), }); await ticket.save(); res.status(200).send(paymentIntent.client_secret); } catch (error) { // 根据错误类型返回对应状态码,更符合HTTP规范 const statusCode = ["活动不存在", "票务已售罄"].includes(error.message) ? 400 : 500; res.status(statusCode).json({ statusCode, message: error.message }); }
额外注意事项
- Stripe金额要求:一定要把金额转换成对应货币的最小单位(比如PLN乘以100,USD乘以100),不然Stripe会直接返回错误,这个坑很容易踩!
- 建议给
Event和Ticket模型加字段校验,比如maxTicketsAmount限制为正整数,ticketPrice限制为正数,提前拦截无效数据。
内容的提问来源于stack exchange,提问作者precel120
相关产品推荐
相关产品推荐

