NestJS/RxJS-是否有更简单的方法;遵守「;一次?
我对NestJS和RxJS都是新手。我正在努力用一个惯用的RxJS编写东西,因为这个项目的目的之一是更好地学习它们,而不是试图绕过或绕过它们的API 总之,我有一个逻辑,我从OAuth2服务器上查找JWKSet。我使用NestJS HttpService来实现这一点,它返回一个可观察的。然后,我使用该可观察对象将结果设置为ReplaySubject。然后,在我的JwtStrategy中,我使用secretroKeyProvider函数订阅ReplaySubject,以便在每次收到HTTP请求时获取值 现在,我确信这种方法有很多错误,因为我几乎不知道如何使用RxJS。我最大的问题是最后一部分。当我在secretroKeyProvider函数中订阅ReplaySubject时,我立即取消订阅。这是因为我想清理剩余订阅 总的来说,我觉得这是非常错误的,订阅和立即取消订阅。我觉得我做错了什么。我正在寻求对该代码的审查,以了解我可以做哪些改进 虽然下面的所有代码都有效,但我的目标是引导我更好、更正确地使用RxJSNestJS/RxJS-是否有更简单的方法;遵守「;一次?,rxjs,nestjs,Rxjs,Nestjs,我对NestJS和RxJS都是新手。我正在努力用一个惯用的RxJS编写东西,因为这个项目的目的之一是更好地学习它们,而不是试图绕过或绕过它们的API 总之,我有一个逻辑,我从OAuth2服务器上查找JWKSet。我使用NestJS HttpService来实现这一点,它返回一个可观察的。然后,我使用该可观察对象将结果设置为ReplaySubject。然后,在我的JwtStrategy中,我使用secretroKeyProvider函数订阅ReplaySubject,以便在每次收到HTTP请求时获
@Injectable()
export class JwkService implements OnModuleInit, OnModuleDestroy {
private readonly logger = new Logger(JwkService.name);
readonly key = new ReplaySubject<string>();
private subscription: Subscription;
constructor(
private httpService: HttpService,
private configService: ConfigService
) {}
onModuleInit(): void {
this.subscription = this.httpService
.get(`${this.configService.get<string>(AUTH_SERVER_HOST)}${jwkUri}`)
.pipe(
map((res: AxiosResponse<JwkSet>) => jwkToPem(res.data.keys[0]))
)
.subscribe({
next: (key) => this.key.next(key),
error: (error: Error) => {
this.logger.error(
'CRITICAL ERROR: Unable to load JWKSet',
ajaxErrorHandler(error)
);
}
});
}
onModuleDestroy(): void {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
private readonly logger = new Logger(JwtStrategy.name);
constructor(
private readonly jwkService: JwkService
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKeyProvider: (
req: Request,
rawJwt: string,
done: doneFn
) => {
jwkService.key
.subscribe({
next: (value: string) => done(null, value),
error: (error: Error) => {
this.logger.error(
'Error getting JWK key',
ajaxErrorHandler(error)
);
done(error);
}
})
.unsubscribe();
}
});
}
}
@Injectable()
导出类JwkService实现OnModuleInit、OnModuleDestroy{
私有只读记录器=新记录器(JwkService.name);
只读键=新的ReplaySubject();
私人认购:认购;
建造师(
私有httpService:httpService,
专用配置服务:配置服务
) {}
onModuleInit():void{
this.subscription=this.httpService
.get(`${this.configService.get(AUTH\u SERVER\u HOST)}${jwkUri}`)
.烟斗(
map((res:AxiosResponse)=>jwkToPem(res.data.keys[0]))
)
.订阅({
下一个:(键)=>这个。键。下一个(键),
错误:(错误:错误)=>{
这是一个错误(
'严重错误:无法加载JWKSet',
ajaxErrorHandler(错误)
);
}
});
}
onModuleDestroy():void{
如果(此订阅){
this.subscription.unsubscripte();
}
}
}
@可注射()
导出类JwtStrategy扩展了PassportStrategy(策略){
私有只读记录器=新记录器(JwtStrategy.name);
建造师(
专用只读jwkService:jwkService
) {
超级({
jwtFromRequest:ExtractJwt.FromAuthHeaderAsberToken(),
忽略过期日期:false,
分泌密钥提供者:(
请求:,
rawJwt:string,
完成:doneFn
) => {
jwkService.key
.订阅({
下一步:(value:string)=>done(null,value),
错误:(错误:错误)=>{
这是一个错误(
'获取JWK密钥时出错',
ajaxErrorHandler(错误)
);
完成(错误);
}
})
.取消订阅();
}
});
}
}
如果您不需要取消订阅
,RxJS会为您提供一些管道:
.get(`${this.configService.get<string>(AUTH_SERVER_HOST)}${jwkUri}`)
.pipe(
take(1),
map((res: AxiosResponse<JwkSet>) => jwkToPem(res.data.keys[0]))
)
...
.get(`this.configService.get(AUTH\u SERVER\u HOST)}${jwkUri}`)
.烟斗(
以(1)为例,
map((res:AxiosResponse)=>jwkToPem(res.data.keys[0]))
)
...
或
.get(`this.configService.get(AUTH\u SERVER\u HOST)}${jwkUri}`)
.烟斗(
第一个(),
map((res:AxiosResponse)=>jwkToPem(res.data.keys[0]))
)
...
first()。如果在任何情况下都没有价值,那么您可以手动取消订阅,或只是完成主题。这很好。还有一个问题,关于错误处理呢?管道似乎无法做到这一点,除非我遗漏了什么。您可以使用catchError管道,然后使用throwError(e=>newerror(e))作为一个简单的解决方案。并在订阅中解析它:subscribe({下一步:()=>{..通常的订阅fn},错误:()=>{..在throwError上执行,},完成:()=>{最后做点什么})
.get(`${this.configService.get<string>(AUTH_SERVER_HOST)}${jwkUri}`)
.pipe(
first(),
map((res: AxiosResponse<JwkSet>) => jwkToPem(res.data.keys[0]))
)
...