[eggjs/egg]发现ctx.runInBackground(scope)并没有不阻塞当前进程异步执行,是什么原因呢?

2025-11-04 644 views
2
What happens?

根据文档的描述,ctx.runInBackground不阻塞当前请求的意思是这个方法里面包含的内容是异步执行么,通过观察线上的日志发现没有异步执行,还是同步的。

How To Reproduce

Steps to reproduce the behavior:

我修改了程序,按照文档示例编写了自己的代码
console.log(1);  
const request = {};  
const config = await ctx.service.api.do1(request);  
console.log(2)
// 下单后需要进行一次核对,且不阻塞当前请求
ctx.runInBackground(async () => {
    // 这里面的异常都会统统被 Backgroud 捕获掉,并打印错误日志
    await ctx.service.api.do2(request);
    console.log(3)
});
console.log(4)
ctx.body = {ok:true}

控制台输出: 1 2 3 4

Expected behavior 1 2 4 3

Context Node Version:v10.15.3 Egg Version:v2.15.1 Plugin Name:none Plugin Version:none Platform:centos7.1

回答

6

提交问题反馈前,请先学习基础的 Markdown 排版

9

没问题,我改一下。

6

Hello @chenjie-cnooc. Please provide a reproducible example following the instruction.

Issues labeled by Need Reproduce will be closed if no activities in 7 days.

@chenjie-cnooc,请根据这个说明提供最小可复现代码。

如果在 7 天内没有进展会被自动关闭。

4

从代码看不出,提交下最小可复现仓库。

7

最小可复现仓库可以弄一个, ctx.runInBackground确定是异步执行的么?

1

我们的所有 API 都是有单测保障的,遇到问题的时候,先提供可复现方式。

如果你有质疑的话,看一眼源码就知道了。https://github.com/eggjs/egg/blob/64efd076bf9d937e36748f89bada6fce186913cd/app/extend/context.js#L210-L241

7

非常感谢

7
//controller
async test(){  
   ctx.runInBackground(async () => {await ctx.service.api.do2(request);});  // #1
   ctx.body = {ok:true}  // #2
}

request:/api/test debug发现:#2已执行,但是一定要等到#1执行完成页面才能得到返回数据,而将#1换成了setTimeout(() => {ctx.service.api.do2(request);},0); 就不存在这个问题,这是什么原因呢?

6

直接给最小可复现方式吧,几分钟就能发现的问题了,这样沟通不累么

4

https://github.com/chenjie-cnooc/eggrunInBackground 最小化項目没问题,同样的代码放到项目里执行就不行了,怪了。

2

意思是这个仓库没法复现? 那就不是最小化复现了。。。 发上来我们也没法看。

那还需要你自己一点点删掉项目的代码来看。

1

项目删除依赖重新安装再试下。

8
//controller
async test(){  
   ctx.runInBackground(async () => {await ctx.service.api.do2(request);});  // #1
   ctx.body = {ok:true}  // #2
}

request:/api/test debug发现:#2已执行,但是一定要等到#1执行完成页面才能得到返回数据,而将#1换成了setTimeout(() => {ctx.service.api.do2(request);},0); 就不存在这个问题,这是什么原因呢?

curl/wget 命令行而不是浏览器访问下试试看有一样的问题不

5
//controller
async test(){  
   ctx.runInBackground(async () => {await ctx.service.api.do2(request);});  // #1
   ctx.body = {ok:true}  // #2
}

请求:/ api / test 调试发现:#2已执行,但是一定要等到#1执行完成页面才能得到返回数据,而将#1换成setTimeout(()=> {ctx.service.api.do2( request);},0); 就不存在这个问题,这是什么原因呢?

curl/wget命令行而不是浏览器访问下尝试看有一样的问题不

最小包没问题,符合预期,但是放在我的项目里不行,怀疑是跟哪个包冲突了。

1

@chenjie-cnooc 看看依赖里有没有 addon,我记得以前有个叫啥包的会把异步转同步,里面起了另一个 eventloop,会有类似这样的现象