Angular+Node.js部署Vercel调用ChatGPT API遇504超时问题求助
解决Vercel部署后ChatGPT接口504超时问题
问题根源
Vercel的Serverless Node.js函数有严格超时限制:免费版最大10秒,Pro版最大60秒。你设置了axios超时30秒,但如果Vercel函数本身的超时阈值更低,就会先触发504错误。
解决方案
1. 调整Vercel函数超时配置(仅适用于响应时间≤60秒场景)
在vercel.json中添加functions字段,明确设置函数最大运行时长:
{ "version": 2, "builds": [ { "src": "server.js", "use": "@vercel/node" }, { "src": "package.json", "use": "@vercel/static-build", "config": { "distDir": "dist/comparison/browser" } } ], "functions": { "server.js": { "maxDuration": 60 // Pro版最大60秒,免费版最多10秒 } }, "rewrites": [ { "source": "/api/(.*)", "destination": "/server.js" }, { "source": "/(.*)", "destination": "/dist/comparison/browser/index.html" } ], "headers": [ { "source": "/api/(.*)", "headers": [ { "key": "Access-Control-Allow-Credentials", "value": "true" }, { "key": "Access-Control-Allow-Origin", "value": "example.com" }, { "key": "Access-Control-Allow-Methods", "value": "GET,OPTIONS,PATCH,DELETE,POST,PUT" }, { "key": "Access-Control-Allow-Headers", "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" } ] } ] }
注意:免费版无法突破10秒限制,此方法仅适合ChatGPT响应能控制在对应时长内的场景。
2. 改用异步处理+前端轮询(彻底解决长耗时请求问题)
将同步等待ChatGPT响应改为异步任务,前端通过轮询获取结果:
步骤1:修改/api/compare接口,返回任务ID
router.post('/api/compare', async (req, res) => { const { v1, v2} = req.body; try { const existing = await Selected.findOne({ v1, v2}); if (existing) { return res.status(200).json({ message: 'already exists.', linkId: existing.linkId }); } // 创建任务记录,状态设为pending const task = await Task.create({ v1, v2, status: 'pending', prompt: `long text` }); // 立即返回任务ID,不等待ChatGPT响应 return res.status(202).json({ taskId: task._id }); } catch (error) { console.error('Error:', error); res.status(500).send('Error processing'); } });
步骤2:新增任务处理逻辑(用定时任务或Vercel Cron Jobs)
创建processTask.js处理ChatGPT请求:
const axios = require('axios'); const Task = require('./models/Task'); const Selected = require('./models/Selected'); async function processPendingTasks() { const pendingTasks = await Task.find({ status: 'pending' }); for (const task of pendingTasks) { try { const response = await axios.post('https://api.openai.com/v1/chat/completions', { model: "gpt-4o-mini", messages: [ { role: "system", content: "You are a helpful assistant." }, { role: "user", content: task.prompt } ], max_tokens: 1000, }, { headers: { 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`, 'Content-Type': 'application/json' }, timeout: 60000 }); // 处理结果并存入Selected表 const result = response.data.choices[0].message.content; await Selected.create({ v1: task.v1, v2: task.v2, linkId: // 生成你的linkId逻辑, result: result }); // 更新任务状态为完成 await Task.findByIdAndUpdate(task._id, { status: 'completed' }); } catch (error) { console.error('Task processing error:', error); await Task.findByIdAndUpdate(task._id, { status: 'failed', error: error.message }); } } } processPendingTasks();
如果用Vercel Cron Jobs(需Pro版),在vercel.json添加定时配置:
{ "crons": [ { "path": "/api/process-tasks", "schedule": "* * * * *" // 每分钟执行一次 } ] }
并在server.js添加路由:
router.get('/api/process-tasks', async (req, res) => { await processPendingTasks(); res.status(200).send('Tasks processed'); });
步骤3:前端轮询任务状态
Angular服务示例:
checkTaskStatus(taskId: string): Observable<TaskStatus> { return this.http.get<TaskStatus>(`/api/check-task/${taskId}`); } // 组件中轮询 startPolling(taskId: string) { this.pollingInterval = interval(3000).pipe( switchMap(() => this.apiService.checkTaskStatus(taskId)), tap(status => { if (status.status === 'completed') { this.loadResult(taskId); clearInterval(this.pollingInterval); } else if (status.status === 'failed') { clearInterval(this.pollingInterval); } }) ).subscribe(); }
后端对应接口:
router.get('/api/check-task/:taskId', async (req, res) => { const { taskId } = req.params; try { const task = await Task.findById(taskId); if (!task) { return res.status(404).json({ message: 'Task not found' }); } if (task.status === 'completed') { const result = await Selected.findOne({ v1: task.v1, v2: task.v2 }); return res.status(200).json({ status: 'completed', linkId: result.linkId, result: result.result }); } return res.status(200).json({ status: task.status }); } catch (error) { console.error('Error checking task:', error); res.status(500).send('Error checking task'); } });
3. 优化ChatGPT请求减少响应时间
- 精简
prompt长度,只保留必要指令 - 调整
max_tokens为实际需要的最小值 - 将
temperature设为0,降低生成随机性以加快响应
内容的提问来源于stack exchange,提问作者Moses Az
相关产品推荐
相关产品推荐

