Me gustaría usar AsyncLocalStorage en un interceptor de NestJs :
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>>; } La función de interceptor obtiene un CallHandler next que devuelve un Observable .
No puedo usar run en este caso (la devolución de llamada de ejecución se cerrará inmediatamente antes de que termine el observable 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()); }Ver ejemplo de repetición rota
La solución que se me ocurrió es esta:
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()) ); } }Ver ejemplo de repetición de trabajo
Esto parece funcionar bien, pero no estoy seguro de si esto es realmente correcto, y parece desordenado y propenso a errores. Entonces me pregunto:
Cómo estoy usando cls-hooks , la solución que encontré fue:
return new Observable(observer => { namespace.runAndReturn(async () => { namespace.set("some", "data") next.handle() .subscribe( res => observer.next(res), error => observer.error(error), () => observer.complete() ) }) })