服务工厂
有时候编写组件或者编写服务,会碰到某个服务有多实例的情况,这个时候服务工厂(Service Factory)就适合这种场景。
比如我们的 oss 组件,由于会创建多个 oss 对象,在编写的时候就需要留好多实例的接口。为了这种场景,midway 抽象了 ServiceFactory
类。
ServiceFactory
是个抽象类,每个需要实现的服务,都需要继承他。
我们以一个 http 客户端为例,需要准备一个创建 http 客户端实例的方法,其中包含两个部分:
- 1、创建客户端实例的方法
- 2、客户端的配置
// 创建客户端的配置
const config = {
baseUrl: '',
timeout: 1000,
};
// 创建客户端实例的方法
const httpClient = new HTTPClient(config);
实现一个服务类
我们希望实现一个上述 HTTPClient 的服务工厂,用于在 midway 体系中创建多个 httpClient 对象。
服务工厂在 midway 中也是一个普通的导出类,作为服务的一员,比如我们也可以把他放到 src/service/httpServiceFactory.ts
中。
1、实现创建实例接口
ServiceFactory
是个用于继承的抽象类,它包含一个泛型(创建的实例类型,比如下面就是创建出 HTTPClient 类型)。
我们只需要继承它。
import { ServiceFactory } from '@midwayjs/core';
import { Provide } from '@midwayjs/decorator';
@Provide()
export class HTTPClientServiceFactory extends ServiceFactory<HTTPClient> {
// ...
}
由于是抽象类,我们需要实现其中的两个方法。
import { ServiceFactory } from '@midwayjs/core';
import { Provide } from '@midwayjs/decorator';
@Provide()
export class HTTPClientServiceFactory extends ServiceFactory<HTTPClient> {
// 创建单个实例
protected createClient(config: any): any {
return new HTTPClient(config);
}
getName() {
return 'httpClient';
}
}
createClient
方法用于传入一个创建服务配置(比如 httpClient 配置),返回一个具体的实例,就像示例的那样。
getName
方法用于返回这个服务工厂的名字,方便框架识别和日志输出。
2、增加配置和初始化方法
我们需要注入一个配置,比如我们使用 httpClient
作为这个服务的配置。
// config.default.ts
export const httpClient = {
// ...
};
然后注入到服务工厂中,同时,我们还需要在初始化时,调用创建多个实例的方法。
import { ServiceFactory } from '@midwayjs/core';
import { Provide } from '@midwayjs/decorator';
@Provide()
export class HTTPClientServiceFactory extends ServiceFactory<HTTPClient> {
@Config('httpClient')
httpClientConfig;
@Init()
async init() {
await this.initClients(this.httpClientConfig);
}
protected createClient(config: any): any {
// 创建实例
return new HTTPClient(config);
}
getName() {
return 'httpClient';
}
}