我正在尝试创建一个可以添加到任何类的 TypeScript 装饰器,它将创建一个请求范围的上下文,我可以使用它来存储请求 ID。我遇到了几篇关于装饰器的文章,但似乎没有一个适合我的用例。
下面是我用来创建异步钩子、装饰器和应该被包装的示例类的代码。运行代码时,我收到的实际响应是一个空对象。上下文正在丢失,但我不知道为什么。我没有收到任何错误或警告。
任何建议将不胜感激。
这是我用来创建上下文的代码。调用initContext()
和getContext()
函数。
import * as asyncHooks from 'async_hooks'
const contexts: any = {}
asyncHooks.createHook({
init: (asyncId: any, type: any, triggerAsyncId: any) => {
if (contexts[triggerAsyncId]) {
contexts[asyncId] = contexts[triggerAsyncId]
}
}
}).enable()
function initContext(fn: any) {
const asyncResource = new asyncHooks.AsyncResource('REQUEST_CONTEXT')
return asyncResource.runInAsyncScope(() => {
const asyncId = asyncHooks.executionAsyncId()
contexts[asyncId] = {}
return fn(contexts[asyncId])
})
}
function getContext() {
const asyncId = asyncHooks.executionAsyncId()
return contexts[asyncId] || {}
}
export { initContext, getContext }
这是我用来包装类的装饰器。我试图在函数的上下文中创建构造initContext
函数,设置上下文 ID,然后返回新的构造函数。
import { initContext } from './lib/context'
function AsyncHooksContext<T extends { new(...args: any[]): {} }>(target: T) {
return initContext((context: any) => {
context.id = 'some-uuid-goes-here'
return class extends target {
constructor(...args: any[]) {
super(...args)
}
}
})
}
export { AsyncHooksContext }
这是一个应该能够生成上下文 ID 的示例类
@AsyncHooksContext
class Foo {
public bar() {
const context = getContext()
console.log('This should be the context => ', { context })
}
}
new Foo().bar()