NestJS v9:实现持久提供程序



[SOLVED]我对NestJS非常陌生,并试图让我的头围绕持久提供程序,但我不能让他们工作。

我的场景是,我有一个服务与一些逻辑和两个提供者实现相同的接口来获取一些数据。根据自定义头值,我想使用Provider1或Provider2,服务本身不需要知道现有的提供程序实现。

因为我在一个请求作用域的场景,但我知道只有2个可能的依赖子树,我想使用持久的提供者,依赖关系不是为每个请求新初始化,而是重用。

我设置了官方文档中描述的ContextIdStrategy,它在每个请求上执行,但我错过了如何将我的提供者实现与在ContextIdStrategy中创建的ContextSubtreeIds连接起来的部分。

<标题>接口:
export abstract class ITest {
abstract getData(): string;
}
<标题>实现:
export class Test1Provider implements ITest {
getData() {
return "TEST1";
}
}
export class Test2Provider implements ITest {
getData() {
return "TEST2";
}
}
<标题>服务:
@Injectable()
export class AppService {
constructor(private readonly testProvider: ITest) {}
getHello(): string {
return this.testProvider.getData();
}
}
<标题>控制器:
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getData(): string {
return this.appService.getData();
}
}
<标题>ContextIdStrategy:
const providers = new Map<string, ContextId>([
["provider1", ContextIdFactory.create()],
["provider2", ContextIdFactory.create()],
]);
export class AggregateByProviderContextIdStrategy implements ContextIdStrategy {
attach(contextId: ContextId, request: Request) {
const providerId = request.headers["x-provider-id"] as string;
let providerSubTreeId: ContextId;
if (providerId == "provider1") {
providerSubTreeId = providers["provider1"];
} else if (providerId == "provider2") {
providerSubTreeId = providers["provider2"];
} else {
throw Error(`x-provider-id ${providerId} not supported`);
}
// If tree is not durable, return the original "contextId" object
return (info: HostComponentInfo) =>
info.isTreeDurable ? providerSubTreeId : contextId;
}
}
<标题>主要:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
ContextIdFactory.apply(new AggregateByProviderContextIdStrategy());
await app.listen(3000);
}
bootstrap();
<标题>模块:
@Module({
imports: [],
controllers: [AppController],
providers: [
{
provide: ITest,
useFactory: () => {
// THIS IS THE MISSING PIECE. 
// Return either Test1Provider or Test2Provider based on the ContextSubtreeId 
// which is created by the ContextIdStrategy
return new Test1Provider();
},
},
AppService,
],
})
export class AppModule {}

缺少的部分是对ContextIdStrategy返回语句的修改:

return {
resolve: (info: HostComponentInfo) => {
const context = info.isTreeDurable ? providerSubTreeId : contextId;
return context;
},
payload: { providerId },
}

修改之后,请求对象可以被注入到模块中,它将只包含providerId属性,基于此,useFactory语句可以返回不同的实现

最新更新