我想在NestJs拦截器中使用AsyncLocalStorage:
export interface CallHandler<T = any> {
handle(): Observable<T>;
}
export interface NestInterceptor<T = any, R = any> {
intercept(context: ExecutionContext, next: CallHandler<T>): Observable<R> | Promise<Observable<R>>;
}
拦截器函数获取一个next
CallHandler
,它返回一个Observable
。
在这种情况下,我不能使用run(run回调将在callHandler.handle()
可观察对象完成之前立即退出):
intercept(context: ExecutionContext, callHandler: CallHandler): Observable<any> | Promise<Observable<any>> {
const asyncLocalStorage = new AsyncLocalStorage();
const myStore = { some: 'data'};
return asyncLocalStorage.run(myStore, () => callHandler.handle());
}
请参见中断的复制-示例
我想出的解决办法是这样的:
const localStorage = new AsyncLocalStorage();
export class MyInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, callHandler: CallHandler): Observable<any> | Promise<Observable<any>> {
const resource = new AsyncResource('AsyncLocalStorage', { requireManualDestroy: true });
const myStore = { some: 'data' };
localStorage.enterWith(myStore);
return callHandler.handle().pipe(
finalize(() => resource.emitDestroy())
);
}
}
型
参见working replit example
这看起来很好用,但我不确定这是否真的正确--而且看起来很混乱,容易出错。
1.这是正确的吗?
1.有没有更好/更干净的方法来处理这个问题?
3条答案
按热度按时间0tdrvxhp1#
下面是我想到的解决方案。我对问题的理解是,您需要
run
函数来接收一个回调函数,该回调函数将完全封装处理程序的执行,然而,intercept
函数预计返回一个尚未触发的可观察对象。这意味着,如果您将可观察对象本身封装在run
回调函数中,它还没有被触发。我的解决方案是返回一个新的observable,当它被触发时,将负责触发(即订阅)调用处理程序本身,因此,我们在
run
调用中创建的promise可以完全封装handle函数及其异步回调。以下是独立函数中的一般功能,以便您可以一起查看:
接下来,我把这个概念和集成到我的拦截器下面。
值得注意的是,在
run
调用过程中创建的Promise
没有拒绝路径,这是故意的,错误会传递给 Package 承诺的可观察对象,这意味着外部可观察对象仍然会成功或出错,这取决于内部可观察对象的行为,然而, Package 内部可观察对象的承诺总是会解决问题。moiiocjp2#
以下是cls-hooks的解决方案:
k7fdbhmy3#
以下是我们目前解决这个问题的方法:
callHandler
localStorage.run
方法中订阅