为何图片上传队列改为async/await写法后仅首个回调可以执行?
问题原因
你在改写async/await版本时的核心问题出在路由处理函数中多余的await img_add调用,非队首请求的路由逻辑会提前执行完毕,导致响应对象失效,后续回调无法正常返回响应,看起来就像只有第一个回调被执行。
具体逻辑分析
原始Promise版本运行正常的原因:
原始版本的路由处理函数是同步函数,调用img_add后直接返回,Express不会主动关闭未返回响应的连接,会等待队列回调中执行res.json/res.status后再返回响应,因此所有请求都能正常触发回调返回结果。async版本出现问题的原因:
你给路由处理函数加了await img_add的逻辑:
- 队首请求进入时,队列长度为1,
img_add会等待当前上传、移除、后续队列全流程执行完成才会resolve,因此第一个请求的回调可以正常执行返回响应。 - 非队首请求进入时,队列长度大于1,
img_add中if(img_queue.length==1)的条件不满足,函数会直接返回resolved状态的Promise,路由中的await立即结束,Express默认认为该请求已处理完成,会自动回收res响应对象或关闭连接,等后续队列处理到该请求、调用回调中的res.json时,已经无法正常发送响应,因此你会误以为后续回调没有执行。
修复方案
最简单的修复就是删除路由处理函数中img_add前的await,和原始版本一样直接调用即可:
router.post('/uploadImg',async(req,res)=>{ // 去掉await,直接调用img_add img_add(posturl,data, (result:any)=>{ res.json(result) }, (err:any)=>{ res.status(500).json(err) } ) })
另外建议优化一个潜在的命名冲突问题:img_add函数形参中的错误回调命名为err,和catch块中的错误对象变量名重名,容易引发变量覆盖问题,建议把catch块的变量名改为error更稳妥。
内容的提问来源于stack exchange,提问作者Atarsei
相关产品推荐
相关产品推荐

