Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如果使用AsyncLocalStorage,如何能够在不被Egg管理的类中,也能正确地拿到上下文对象 #5271

Closed
ljj0915 opened this issue Nov 13, 2023 · 12 comments · Fixed by eggjs/egg-core#266 or eggjs/egg-core#267
Assignees

Comments

@ljj0915
Copy link

ljj0915 commented Nov 13, 2023

1.Egg里面,大部分的业务代码可能写在了Service、Controller层,这些可以通过继承Egg里面的对应类来完成被Egg管理。这样就能通过this.ctx拿到上下文对象。
2.问题是:如果有很多对象,都是通过new出来的话,就是无法直接从this.ctx拿到上下文。我想通过全局的对象拿到一个上下文。考虑到AsyncLocalStorage。

写法:
1.定义一个storage并暴露出去:
const { AsyncLocalStorage } = require('async_hooks');
const storage = new AsyncLocalStorage();
export default storage;

2.中间件里面(按顺序执行的第一个中间件)添加一个Context或者一个uuid也好:
import {storage} from './storage'
await storage.run(context, async () => await next());

3.在任意的地方,通过拿第一步的storage,再拿到storage存储的内容:
import {storage} from './storage'
console.log(storage.getStore())

上面的这个写法,对于本地开发下,单次http请求是没有任何问题的,但是我发现,在频率高的情况下,值就窜了,比如uuid。请问这样写是否有问题,以及有没有更好的解决方案或者思路。我在想为何会出现值窜的情况?

@atian25
Copy link
Member

atian25 commented Nov 13, 2023

https://github.com/search?q=org%3Aeggjs+AsyncLocalStorage&type=pullrequests

egg/index.d.ts

Line 740 in ad6c06a

get ctxStorage(): AsyncLocalStorage<Context>;

可以参考下

@ljj0915
Copy link
Author

ljj0915 commented Nov 13, 2023

https://github.com/search?q=org%3Aeggjs+AsyncLocalStorage&type=pullrequests

egg/index.d.ts

Line 740 in ad6c06a

get ctxStorage(): AsyncLocalStorage<Context>;

可以参考下

你好,这个方式应该也需要类继承对应的Application吧,如果是不继承呢,全局任意一个地方可以拿的

@fengmk2
Copy link
Member

fengmk2 commented Nov 13, 2023

@laoboxie
Copy link

laoboxie commented Dec 5, 2023

我也遇到一样的问题,希望ctxStorage能够在任意地方获取到,场景是一些sdk需要拿到当前的上下文ctx。
目前没想到比较好的方法来解决这个问题。
ctxStorage是不是应该设计为在任意地方都能方便地获取到呢?

@fengmk2
Copy link
Member

fengmk2 commented Dec 5, 2023

只要拿到 app 就能获取到 app.ctxStorage 了

@killagu
Copy link
Contributor

killagu commented Dec 14, 2023

搞一个 Symbol 然后挂到全局类似于 global[Symbol.for('egg#ctxStorage')] ?

@fengmk2
Copy link
Member

fengmk2 commented Dec 14, 2023

搞一个 Symbol 然后挂到全局类似于 global[Symbol.for('egg#ctxStorage')] ?

好像可以哦,就算多个 app 实例,共用一个 als 似乎也是可以正常工作的。

@fengmk2 fengmk2 self-assigned this Dec 14, 2023
@fengmk2 fengmk2 added the core label Dec 14, 2023
@fengmk2
Copy link
Member

fengmk2 commented Dec 19, 2023

在 egg app 初始化之后,对 global 对象做赋值 https://github.com/koajs/koa/blob/v2.x/lib/application.js#L71 ,实现全局获取当前 als 能力。

@fengmk2
Copy link
Member

fengmk2 commented Dec 19, 2023

@ljj0915 可以通过 global[Symbol.for('egg#ctxStorage')] 获取了。

eggjs/egg-core#268

使用 https://github.com/node-modules/gals 库可以获得,统一封装。

@fengmk2 fengmk2 closed this as completed Dec 19, 2023
fengmk2 added a commit to eggjs/egg-core that referenced this issue Dec 19, 2023
@ljj0915
Copy link
Author

ljj0915 commented Dec 25, 2023

@ljj0915 可以通过 global[Symbol.for('egg#ctxStorage')] 获取了。

eggjs/egg-core#268

使用 https://github.com/node-modules/gals 库可以获得,统一封装。

后来我自己使用AsyncLocalStorage,全局定义了一个,每次进来,在中间件里面,把next()包进去,后续任意一个地方都可以拿到了。差不多

@fengmk2
Copy link
Member

fengmk2 commented Dec 31, 2023

egg >= 2.x 都支持从 gals 获取了。

@laoboxie
Copy link

优秀!可以愉快地进行异步上下文追踪了~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants