后端开发笔记:eggjs 使用随笔

May 10, 2024·
Sam.C
Sam.C
· 2 min read
文档总也看不熟。总是会踩坑,记录一下,有个回头看的地方吧。

今天遇到的奇怪的报错是路由定义好了,控制器和服务都写好了,就是一直报错启动不起来,报错是:

2024-05-12 08:09:36,597 ERROR 14124 [-/127.0.0.1/-/14ms GET /api/get-unitconversions] nodejs.TypeError: Cannot read properties of undefined (reading 'getUnitConversions')
    at UnitConversionController.getUnitConversions (C:\work\mbos_saas\app\controller\unitconversion.js:62:63)
    at Object.callFn (C:\work\mbos_saas\node_modules\egg-core\lib\utils\index.js:44:21)
    at Object.classControllerMiddleware (C:\work\mbos_saas\node_modules\egg-core\lib\loader\mixin\controller.js:87:20)
    at Object.callFn (C:\work\mbos_saas\node_modules\@eggjs\router\lib\utils.js:12:21)
    at wrappedController (C:\work\mbos_saas\node_modules\@eggjs\router\lib\egg_router.js:322:18)
    at dispatch (C:\work\mbos_saas\node_modules\@eggjs\router\node_modules\koa-compose\index.js:44:32)
    at next (C:\work\mbos_saas\node_modules\@eggjs\router\node_modules\koa-compose\index.js:45:18)
    at C:\work\mbos_saas\node_modules\@eggjs\router\lib\router.js:186:18
    at dispatch (C:\work\mbos_saas\node_modules\@eggjs\router\node_modules\koa-compose\index.js:44:32)
    at C:\work\mbos_saas\node_modules\@eggjs\router\node_modules\koa-compose\index.js:36:12
headers: {"Access-Control-Allow-Origin":"http://localhost:8000","Access-Control-Allow-Credentials":"true","vary":"Origin"}
pid: 14124
hostname: DESKTOP-MF9BLRQ

一直说找不到这个方法。但是明明控制器和服务中都定义了的。

最后把路由器中的 this.service.unitConversion.getUnitConversions 中的服务名改成小写而解决 unitconversion 。一个字母大小写引发的惨案。

编写规范

  • 错误传递非常重要:eggjs 已经内置了统一的错误处理模块,几乎不用特别的处理,在写 service 时,使用 try catch 块把 prisma 的操作包裹起来是很有必要的,在 catch 块中,可以 return 一个对象,有一个 message 属性,属性的值根据使用的数据库操作方式而不同,如果使用 prisma ,那可以是:
try{

}
catch(error){
  return {
    message: error.meta
  }
}

catchreturn 的对象会被传递给控制器,写入 ctx.body 中。而 metaprisma 内部错误处理机制的核心成员,包括和出错的模块和原因。

  • 最好不要把 ctx 直接传递给 servicecontroller 用于接收、解构 request 对象的值并进行验证(可以使用 Joi 验证库,非常好用)和封装 response 对象,结构出的值经过验证以后,传递给 service ,使之专注于数据库操作和核心业务逻辑的实现,和 controller 各司其职。

  • controller 中,可以直接使用 this.service 直接获取到当前请求上下文的 Service 对象,可以直接调用 service 中定义的方法。而在 service 中,就需要通过构造函数显示引入的方式,才能访问 app 启动时挂载的服务:

class UnitService extends Service {
  constructor(props) {
    super(props)
    this.prisma = this.ctx.app.prisma;
    this.casdoor = this.ctx.app.casdoor;
  }
  async getUnit(id) {

  }
  }
  • 以上定义的错误返回方式,一般可以很好的反应导致错误的原因,但是有时候也会有例外。

  • 路由路径可以有多种组装方式, router.put('unit', '/api/update-unit/:ownerId/:id', controller.unit.updateUnit); 这种方式可以通过 this.ctx.params 获取到路由路径中的 ownerIdid,其他内容还是通过 this.ctx.request.bodythis.ctx.query (查询参数)获取。