无返回值Promise链式调用最佳实践(Express服务场景)
问题解决及最佳实践建议
1. 空响应的规范写法
你现在用res.send(undefined)的方式不符合HTTP语义,更规范的做法是直接返回 204 No Content 状态码:
res.sendStatus(204)
204是HTTP标准定义的「请求处理成功、无返回内容」的状态码,不会附带任何响应体,完全匹配你当前的业务场景。
2. Promise 逻辑优化
你当前的代码混用async/await和.then,嵌套层级深,容易出现异步漏捕获、逻辑顺序出错的问题,建议全用async/await改写拍平逻辑,可读性和可维护性都更高:
app.post("/pdf", async (req, res) => { res.contentType("application/json"); try { if (req.body.layout.callsheet) { await toPNG.pdfToPNG(req.body.layout.callsheet, pdfPath); await generatePDf(req.body.data, pdfPath, req.body.layout.selected); if (layout === "landscape") { await call.doubleCover(`${pdfPath}`, `${pdfPath}-coverSheet.png`); } else { await call.singleCover(`${pdfPath}`, `${pdfPath}-coverSheet.png`); } } else { await generatePDf(req.body.data, callSheet); } res.sendStatus(204); } catch (err) { console.error(err); res.status(500).send(err.toString()); } });
3. Heroku 超时问题解决
Heroku 路由层默认有30秒的超时限制,只要你的请求处理超过30秒,不管你服务端逻辑有没有跑完,Heroku都会主动断开连接返回503错误。如果你处理大数据集的耗时经常超过30秒,同步等处理完再返回的模式是走不通的,建议改成异步任务模式:
- 接口收到请求后,先把PDF生成任务存入持久化队列(推荐基于Redis的BullMQ,简单场景也可以用内存队列),立刻返回
202 Accepted状态码,同时返回任务ID - 后端单独跑worker进程消费队列里的任务,处理完后更新任务状态
- 前端拿到任务ID后定时轮询查询任务状态,处理完成后再给用户提示
这种模式完全不会触发超时限制,也能更好的应对任务堆积的场景。
内容的提问来源于stack exchange,提问作者Timotronadon
相关产品推荐
相关产品推荐

