midway 框架 Service 与 Servide 的调用、合并导出与注入的实现方式
一、midway service 与 egg service 的区别
midway 的 serivce 与 egg 的 service 没有什么区别,只不过 midway 通过 IOC 的方式更加方便组织 service
egg 中的 service
在 egg 中,我们定义并且实现一个 service 代码可能如下:
// app/service/user.js
const Service = require('egg').Service;
class UserService extends Service {
async find(uid) {
const user = await this.ctx.db.query('select * from user where uid = ?', uid);
return user;
}
}
module.exports = UserService;
如果要使用一个 service,不需要特殊的引入操作,直接通过上下文信息 this.ctx.service.xxx
调用即可。
// app/router.js
module.exports = app => {
app.router.get('/user/:id', app.controller.user.info);
};
// app/controller/user.js
const Controller = require('egg').Controller;
class UserController extends Controller {
async info() {
const { ctx } = this;
const userId = ctx.params.id;
const userInfo = await ctx.service.user.find(userId);
ctx.body = userInfo;
}
}
module.exports = UserController;
midway 中的 service
midway 中, service 通过 IOC 控制反转的方式定义和使用 service,并且在启动的时候做了扫描和注入的工作,声明实现一个 service 的时候不再需要继承 egg.Service
。
如果要定义一个 service 只需要通过 @provide
注解声明即可
import { provide } from "midway";
import { IHttpService } from '../interfaces/http';
@provide('httpService')
export class HttpService implements IHttpService {
// 模拟 HTTP GET
async get() {
return Promise.resolve({
res: true,
message: 'message'
});
}
}
当然上面的代码中,IHttpService 只是我自己定义的一个接口而已,不是关键信息。
我们可以看到 @provide('httpService')
已经通过注解声明了名称为 httpService
的 service,注意这里并没有显示的去继承 Service
声明实现了一个 service 之后,就可以在应用内通过 @inject('serviceName')
的方式引入 service:
@inject('httpService')
http: any
@get('/http/test')
async httptest(ctx: Context) {
this.ctx.body = await this.http.get();
}
效果:
二、midway 实现 service 的相互调用
有的时候我们可能需要在某个 service 中调用另外一个 service,IoC 的实现方式,能够方便我们在实现了一个 service 之后,在其他地方比如plugin、extend、service、controller 中通过 @inject
引入 service
比如现在有一个 componentService 需要调用上面声明的 httpService:
@provide('componentService')
export class ComponentService implements IComponentService {
@inject('httpService')
http: any
async create(): Promise<IComponentDTO> {
const res = await this.http.get();
return Promise.resolve(res);
}
}
在 ComponentService
中,实现了接口 IComponentService,并且通过 @inject('httpService')
注入了 httpService,使得我们能够在代码中直接调用 this.http.get()
service 的相互调用在某种程度上使得项目的协作开发与依赖拆分更加方便,项目的维护成本也降低很多。
三、midway 中实现多个 service 合并输出
有些场景下,一个 service 可能实现的代码太多了,一个文件可能放不下,也不利于维护,代码量太大,旺旺这种场景下我们会考虑拆分 service。
比如我有一个 service,需要操作 component 和 page,而 component 和 page 每个服务本身有很多方法和代码,我拆分了两个文件并且放在一个文件夹中,目录如下组织:
实现的 page.ts 如下:
import { provide } from 'midway';
@provide('pageService')
export class PageService {
async getById(id: string | number): Promise<any> {
return new Promise((resolve, reject) => {
resolve({ pageId: id, name: 'name' })
});
}
}
实现的 componentService 如下:
import { provide, inject } from 'midway';
import { IComponentDTO, IComponentService } from '../../interfaces/component';
// import { IHttpService } from '../interfaces/http';
@provide('componentService')
export class ComponentService implements IComponentService {
@inject('httpService')
http: any
async create(): Promise<IComponentDTO> {
const res = await this.http.get();
return Promise.resolve(res);
}
}
最终目的是将 componentService 和 pageService 合并到一个 service,也就是在 controller 中使用的时候,我只需要 inject 一个 service。
这个时候 IoC 的优点又体现出来,我们只需要在要对外暴露出来的文件中,将 componentService 和 pageService 注入进来即可,因为当注入进来之后,当前 Service 实例上会自动挂载 this.component
和 this.page
,并且会对外抛出来:
import { provide, inject } from 'midway';
@provide('testService')
export class TestService {
@inject('componentService')
component: any
@inject('pageService')
page: any
}
如果需要在 controller 中使用这个 service,我们只需要 @inject testService
这个 service 即可,然后调用代码中,通过如下方式调用:
@inject('testService')
test: any
@get('/test/test')
async testtest() {
const id: number | string = 123;
const demoComponent: IComponentDTO = {
id: '123',
latestVersion: '1.2.2',
name: 'test-name'
};
const componentInfo = await this.test.component.update(id, demoComponent);
this.ctx.body = { success: true, message: '', data: componentInfo };
}
最终效果和直接 inject componentService 是一样的:
四、不要尝试嵌套 inject 注入 service
比如 serviceA inject 了 serviceB,serviceB 又 inject 了 serviceA
千万不要做这样的事情
千万不要做这样的事情
千万不要做这样的事情
死循环会直接崩掉。
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://www.ptbird.cn/midway-service.html
转载请注明文章原始出处 !