Service / 服务

项目中,有时候除了查询数据库等操作外,也需要调用远程的一些接口,如:调用 GitHub 的接口、调用发送短信的接口等等。

这种功能放在 Model 下是不太合适的,为此,框架提供了 Service 来解决此类问题。

创建 Service 文件

Service 文件存放在 src/service/ (多模块在 src/common/service/)目录下,文件内容格式如下:

  1. module.exports = class extends think.Service {
  2. constructor() {
  3. }
  4. xxx() {
  5. }
  6. }

Service 都继承 think.Service 基类,但该基类不提供任何方法,可以通过 Extend 进行扩展。

可以在项目根目录下通过 thinkjs service xxx 命令创建 service 文件,支持多级目录。

实例化 Service 类

可以通过 think.service 方法实例化 Service 类,在控制器、ctx 也有对应的 service 方法,如:ctx.servicecontroller.service,这些方法都是 think.service 的快捷方式。

项目启动时,会扫描项目下所有的 services 文件,并存放到 think.app.services 对象下,实例化时会从该对象上查找对应的类文件,如果找不到则报错。

无参数类的实例化

  1. // src/service/sms.js
  2. module.exports = class extends think.Service {
  3. xxx() {
  4. }
  5. }
  6. // 实例化,没有任何参数
  7. const sms = think.service('sms');
  8. sms.xxx();

有参数类的实例化

  1. // src/service/sms.js
  2. module.exports = class extends think.Service {
  3. constructor(key, secret) {
  4. super();
  5. this.key = key;
  6. this.secret = secret;
  7. }
  8. xxx() {
  9. }
  10. }
  11. // 带参数的实例化
  12. const sms = think.service('sms', key, secret);
  13. sms.xxx();

多模块项目的实例化

  1. // src/home/service/sms.js
  2. module.exports = class extends think.Service {
  3. constructor(key, secret) {
  4. super();
  5. this.key = key;
  6. this.secret = secret;
  7. }
  8. xxx() {
  9. }
  10. }
  11. // 指定从 home 下查找 service 类
  12. const sms = think.service('sms', 'home', key, secret);

多级目录的实例化

  1. // src/service/aaa/sms.js
  2. module.exports = class extends think.Service {
  3. xxx() {
  4. }
  5. }
  6. const sms = think.servie('aaa/sms');

扩展 Service 类的方法

基类 think.Service 没有提供任何的方法,但实际中需要用到很多常用的方法,如:从远程接口获取数据的模块,处理完数据后将数据更新到数据库的操作。这个时候可以通过对应的扩展来加强 think.Service 类的功能,如:

  • think-fetch 模块让 think.Service 类有了 fetch 方法,这样很方便获取远程的数据
  • think-model 模块让 think.Service 类有了 model 方法,这样可以快速的操作数据库
    这些模块都是 Extend/扩展,可以增强 think.Service 类的能力。

当然项目中也可以根据需要扩展 think.Service 类,如:

  1. // src/extend/service.js
  2. module.exports = {
  3. getDataFromApi() {
  4. }
  5. }

通过在扩展文件 src/extend/service.js(多模块项目为 src/common/extend/service.js)添加对应的方法,增强 think.Service 类的能力,这样在 src/service/xxx.js 中就可以直接使用这些方法了。

  1. // src/service/sms.js
  2. module.exports = class extends think.Service {
  3. async xxx() {
  4. const data = await this.getDataFromApi(); // 这个访问为 extend/service.js 里扩展的方法
  5. }
  6. }

如果这些扩展的方法比较通用,那么就可以整理成一个 Extend 模块发布,其他项目引入这个模块就可以了,具体见 Extend/扩展

原文: https://thinkjs.org/zh-cn/doc/3.0/service.html