Node+Express异步代码出现未处理Promise错误与响应头重复发送问题
问题分析与修复方案
你的代码存在两个核心问题:
- 重复响应客户端:当数据库保存失败时,catch块已发送400响应,但函数后续仍执行到最后的201响应,导致试图在响应已发送后再设置头信息,触发
ERR_HTTP_HEADERS_SENT错误。 - 未处理OpenAI API调用异常:调用OpenAI的两个
createCompletion方法时无错误捕获,一旦API调用失败,会抛出未处理的Promise拒绝,触发UnhandledPromiseRejectionWarning。
修复步骤
- 统一错误处理流程:将所有异步操作(OpenAI调用、数据库保存)包裹在同一个try/catch块中,确保每个请求只发送一次响应。
- 终止错误后的后续执行:在catch块处理错误后用
return终止函数,避免重复响应。 - 并行优化OpenAI请求:用
Promise.all并行执行两个OpenAI请求,提升性能。
修改后的完整代码
const { Configuration, OpenAIApi } = require("openai"); // 创建用户数据 const createUserData = async (req, res) => { const { transcript } = req.body; // 移除未使用的id、scores参数 const user_id = req.user._id; const configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); try { // 并行发起两个OpenAI请求,减少总等待时间 const [feedbackResponse, scoreResponse] = await Promise.all([ openai.createCompletion({ model: "text-davinci-002", prompt: `Provide personal feedback for me and give me tips: ${transcript}`, temperature: 1, max_tokens: 200, top_p: 1, frequency_penalty: 0, presence_penalty: 0, }), openai.createCompletion({ model: "text-davinci-002", prompt: `Give this text a number from 1-100 in terms of positivity: ${transcript}`, temperature: 1, max_tokens: 100, top_p: 1, frequency_penalty: 0, presence_penalty: 0, }) ]); // 清理返回文本的多余空格/换行 const feedbackText = feedbackResponse.data.choices[0].text.trim(); const scoreText = scoreResponse.data.choices[0].text.trim(); const newUserData = new UserData({ id: 'user', scores: scoreText, transcript: transcript, user_id: user_id, feedback: feedbackText }); console.log(newUserData); await newUserData.save(); console.log('POST:', newUserData); return res.status(201).json({ user_data: newUserData, feedback: feedbackText, score: scoreText }); } catch (error) { console.error('请求出错:', error); // 统一返回错误响应,终止函数执行 return res.status(400).json({ error: error.message }); } };
额外优化说明
- 并行处理OpenAI请求,相比原串行执行减少了一半左右的等待时间。
- 对OpenAI返回的文本做
trim()处理,避免多余的空白字符影响数据存储。 - 移除未使用的参数,简化代码结构。
内容的提问来源于stack exchange,提问作者Soccerball123
相关产品推荐
相关产品推荐

