Node.js报错时关闭Post请求连接并返回Postman响应
问题:Express邮件接口报错时Postman无限加载,无法返回响应
我用Express写了一个邮件发送接口,当sendEmail执行报错时(代码注释标记位置),Postman会无限加载,没法收到响应。试过返回不同的res.json数据但没用,相关代码如下:
import express, { Request, Response } from "express"; import { sendEmail } from "../../mailsend/SendMail"; // будт приходить с клиента три массива [connectionData: {from, pass}] [sendMail: {to}] [dataText: {subject, text}] const routerMailSend = express.Router(); routerMailSend.post("/", async (req: Request, res: Response) => { if (!req.body) { return res.status(400).send("Missing from property in request body"); } console.log(req.body); const { connectionData, dataText, sendMail } = req.body //В таком виде будут приходить с клиента массивы // const { from, pass, to, subject, text } = req.body; try{ const promises = sendMail.map(async (recipient: string) => { const {from, pass} = connectionData[Math.floor(Math.random() * connectionData.length)]; const {subject, text} = dataText[Math.floor(Math.random() * dataText.length)]; console.log(from, pass); return new Promise((resolve, reject) => { setTimeout( async () => { try { const transfer = await sendEmail(from, pass, recipient, subject, text); console.log("message send process"); resolve(transfer); } catch (err) { console.log("Connect refused"); reject(new Error("Incorrect login or password")) // ----------Close the post request connection if an error occurs at this location and return the response to postman } }, Math.floor(Math.random() * (10000 - 3000 + 1) + 3000)) }) }) const results = await Promise.all(promises); res.status(200); return res.json({ message: "Message send access" }); } catch (err) { res.status(400); return ({ message: "Message send error" }); } }); export default routerMailSend;
解决方案
问题根源
Promise.all错误捕获后的响应缺失:虽然Promise.all会在任一Promise reject时抛出错误,但你的catch块只是返回了一个对象,没有调用res.json()或res.send()来结束请求,导致Postman一直等待响应。- 冗余的Promise嵌套:手动创建Promise包裹
setTimeout和异步逻辑,写法冗余且容易出错。
修改后的代码
import express, { Request, Response } from "express"; import { sendEmail } from "../../mailsend/SendMail"; const routerMailSend = express.Router(); routerMailSend.post("/", async (req: Request, res: Response) => { if (!req.body) { return res.status(400).send("Missing from property in request body"); } console.log(req.body); const { connectionData, dataText, sendMail } = req.body; try { const promises = sendMail.map(async (recipient: string) => { // 随机选取邮件配置 const { from, pass } = connectionData[Math.floor(Math.random() * connectionData.length)]; const { subject, text } = dataText[Math.floor(Math.random() * dataText.length)]; console.log(from, pass); // 简化延迟逻辑,避免手动创建Promise await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * (10000 - 3000 + 1) + 3000))); // 执行邮件发送,失败直接抛出错误 const transfer = await sendEmail(from, pass, recipient, subject, text); console.log("message send process"); return transfer; }); await Promise.all(promises); return res.status(200).json({ message: "Message send access" }); } catch (err) { console.log("Connect refused", err); // 必须调用res.json返回响应,主动结束请求 return res.status(400).json({ message: "Message send error", error: (err as Error).message }); } }); export default routerMailSend;
可选优化:快速失败模式
如果需要在第一个错误发生时立即返回响应(无需等待所有Promise完成),可以替换Promise.all为循环逐个执行:
try { for (const recipient of sendMail) { const { from, pass } = connectionData[Math.floor(Math.random() * connectionData.length)]; const { subject, text } = dataText[Math.floor(Math.random() * dataText.length)]; console.log(from, pass); await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * (10000 - 3000 + 1) + 3000))); await sendEmail(from, pass, recipient, subject, text); console.log("message send process"); } return res.status(200).json({ message: "Message send access" }); } catch (err) { console.log("Connect refused", err); return res.status(400).json({ message: "Message send error", error: (err as Error).message }); }
内容的提问来源于stack exchange,提问作者Seven Elevon
相关产品推荐
相关产品推荐

