Express.js使用async/await/Promise时接口响应无返回结果问题求助
核心问题分析
你两次代码返回空数组的核心原因是没有等待所有异步任务执行完成就提前返回了响应:
- 初始写法未对Promise做任何等待处理,
res.send执行时所有文档处理逻辑还处于pending状态,result数组尚未被赋值。 - 第二次改写仅给单个文档处理逻辑加了async自执行函数,主线程不会等待这些独立的异步任务执行完成,仍然会提前执行
res.send,后续异步任务执行完往result中填充数据时,响应已经发送完成,因此会出现控制台能打印到值但接口返回为空的情况。
另外你封装的三个服务处理函数也存在逻辑问题:如果xxxService.process本身是异步方法,你当前的同步resolve(data)只会拿到pending状态的返回值,且resolve和reject同步先后书写时,reject永远不会触发,完全没有错误处理能力。
修复步骤
步骤1:修正服务处理函数的Promise封装
如果xxxService.process本身返回Promise,无需手动包装new Promise,直接返回即可:
function lookUpServiceProcessor(element){ const lookUpService = new LookUpService(); return lookUpService.process(element); } function keywordServiceProcessor(element){ const keywordService = new KeywordService( process.env.KEYWORD_SERVICE_HOSTNAME, process.env.KEYWORD_SERVICE_PORT, process.env.KEYWORD_SERVICE_ENDPOINT ); return keywordService.process(element); } function patternServiceProcessor(element){ const patternService = new PatternService( process.env.PATTERN_SERVICE_HOSTNAME, process.env.PATTERN_SERVICE_PORT, process.env.PATTERN_SERVICE_ENDPOINT ); return patternService.process(element); } const processEachDocument = (document) => { return Promise.all([ lookUpServiceProcessor(document), keywordServiceProcessor(document), patternServiceProcessor(document) ]); }
如果xxxService.process是回调风格的异步方法,按如下方式正确封装Promise:
// 以lookUpServiceProcessor为例,其他两个同理修改 function lookUpServiceProcessor(element){ return new Promise((resolve, reject) => { const lookUpService = new LookUpService(); lookUpService.process(element, (err, data) => { if(err) return reject(err); resolve(data); }) }) }
步骤2:修正路由的异步等待逻辑
给路由处理函数加上async关键字,用Promise.all等待所有文档的处理任务全部完成后再返回响应:
router.post('/extraction', async (req, res) => { try { // 等待所有文档处理任务完成 const result = await Promise.all( req.body.map(document => processEachDocument(document)) ); res.send(result); } catch (error) { // 按需调整错误返回格式 res.status(500).send({ msg: '文档处理失败', error: error.message }) } })
如果需要实现单个文档处理失败不影响其他文档的返回,可给单个处理逻辑加catch捕获错误:
router.post('/extraction', async (req, res) => { const result = await Promise.all( req.body.map(document => processEachDocument(document) .catch(err => ({ status: 'fail', error: err.message, originDocument: document })) ) ); res.send(result); })
内容的提问来源于stack exchange,提问作者Hari Rao
相关产品推荐
相关产品推荐

