Node.js+Express中使用formidable提交表单遇未处理Promise报错
问题根因
- 执行顺序错误:
form.parse()是回调式异步方法,你定义的回调函数会在后续事件循环阶段才执行,外层代码不会等待回调执行完成,就会提前执行res.status(201).send(post created ${post}),此时post还是未赋值的undefined,且提前返回响应后,回调内部如果再操作响应对象会触发报错。 - 错误捕获失效:外层的
try/catch只能捕获当前同步执行阶段的错误,回调内部异步代码抛出的Promise错误无法被外层捕获,就会出现未处理Promise的报错。 - 重复响应冲突:如果回调内部已经执行了
res.status(401).send()或res.status(500).send()返回响应,外层的201响应会再次触发,express不允许同个请求返回多次响应,会抛出额外错误。
修复方案
把form.parse封装为Promise适配async/await语法,统一错误捕获和响应逻辑,修正后的代码如下:
const express=require("express"); const Post =require("../DB/Postmodel"); const formidable=require("formidable"); const fs=require("fs").promises; const _ = require("lodash"); const router= express.Router(); router.get('/', ( req, res)=>{ res.send(`hello from the other side`) }); router.post("/create", async(req, res)=>{ try { const form= new formidable.IncomingForm(); form.keepExtensions= true; // 把form.parse封装为Promise,用await等待执行完成 const [fields, files] = await new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) return reject(err); resolve([fields, files]); }) }) const post= new Post(fields); if(files.postPic){ post.postPic.data= await fs.readFile(files.postPic.path); post.postPic.contentType= files.postPic.type; } await post.save(); // 所有逻辑执行完成后再返回响应 res.status(201).send(`post created ${post}`) } catch (error) { // 统一捕获所有阶段的错误 console.log(error); // 检查响应是否已经发送,避免重复发送报错 if (!res.headersSent) { res.status(500).send(`请求处理失败:${error.message || error}`) } } }) module.exports=router;
内容的提问来源于stack exchange,提问作者Dhyanjyoti Das
相关产品推荐
相关产品推荐

