【发布时间】:2022-11-18 01:26:39
【问题描述】:
[已解决] 我是 NestJS 的新手,我试图了解持久的提供者,但我无法让他们工作。
我的场景是我有一个具有一些逻辑的服务和两个实现相同接口以获取一些数据的提供者。根据我想使用 Provider1 或 Provider2 的自定义标头值,服务本身不必了解现有的提供程序实现。
因为我在一个请求范围的场景中,但我知道只有 2 个可能的依赖子树,我想使用持久的提供者,依赖不是为每个请求重新初始化,而是重用。
我按照官方 docs 中的描述设置了 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();
}
}
上下文 ID 策略:
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 {}
【问题讨论】: