[eggjs/egg][Feature Request] controller 和 service 的定义可以不用继承 egg.Service

2024-08-05 307 views
8
Background

目前约定 controller 和 service 固定在 app/controller 和 app/service 两个目录,既然已经有了约定,那如下写法是否可以抛弃掉,直接使用 module.exports = {} 来定义?

原写法:

const egg = require('egg');

class HomeController extends egg.Controller {
    home(){
    // do sth
    }
}

简化后的写法:

module.exports = {
    home(){
    // do sth
    }
}

可参考我扩展的框架 egg-mongoose-framework:

https://github.com/yisbug/egg-mongoose-framework/blob/master/test/fixtures/example/app/controller/home.js

回答

6

实际上,这是 egg 1.0 最早支持的方式,你可以试下,默认就支持的。

egg 2.0 也还支持这种写法,只不过我们推荐用 Class 的方式。

2

为什么推荐用 Class 的方式呢?这样其实不利于复用

2

另外 module.exports 这种写法是不是特殊处理过?我没仔细看源码,只是在重写 loadService 和 loadController 这两个方法的时候发现有一些差异。

6

我们实践下来发现 Class 的方式更好

  1. Controller 不是用来复用的,复用的逻辑应该在 Service。exports 和复用也没啥关系。
  2. 继承的方式可以便于提供基类方法,如 this.success() 啥的。
  3. 如果后面要用 TS 啥的,只能是 class 才有装饰器。

没特殊处理过,你可以看下 file loader 那里,如果是 class 会实例化,不是则直接使用。

2
  1. 我主要指的就是 service 复用,比如一些方法,是放在helper 里还是 service,有些时候需要斟酌一下。exports 的话可以直接复制文件拿来用。一些第三方的模块也可以直接 copy 文件过来使用。当然,话说回来,你既然说已经支持了,那我这些也基本是废话了。
  2. controller 也有复用的场景啊,比如我写的那个框架,就是需要复用一部分 RESTful 的接口,利用 schema 中定义的规则校验参数,然后调用 service 处理。这几个接口的逻辑是一模一样的。
6

复用不应该是复制文件吧,可以通过 class 继承的方式来复用啊,你提供自定义的 BaseController 就可以了。

2

我最初的实现就是定义一个 BaseController,其他 controller 继承。后来觉得 BaseController 有点重了,希望更简单纯粹一些。这个可能是理解上的差异吧,我个人感觉 app 目录下所有文件都使用 exports 感觉更好。

8

嗯,看个人喜好,我们实践下来是 Class 方式不错。而且我们不是一个 BaseController,而是可能有 RPCBaseController,HTTPBaseController 等等。

不过 exports 还是会支持的,你可以直接用。