比nestjs更优雅的ts控制反转策略-依赖查找

一、Cabloy5.0内测预告

Cabloy5.0采用TS对整个全栈框架进行了脱胎换骨般的大重构,并且提供了更加优雅的ts控制反转策略,让我们的业务开发更加快捷顺畅

1. 新旧技术栈对比:

后端 前端
旧版 js、egg2.0、mysql js、vue2、framework7
新版 ts、egg3.0、多数据库兼容(支持mysql、postgresql) ts、vue3、quasar

2. 框架开发两大趋势

  1. TS化:这是显而易见的趋势,不必赘言

  2. ESM化:从目前趋势看,前端框架已经全链路ESM化了,但是,大多数后端框架仍然是Commonjs。即便是egg3.0也仍然是Commonjs。由于egg的定位仍然是元框架,CabloyJS5.0在egg基础上仍然开发出了全量ESM化的业务模块化系统(在Commonjs之上进行ESM化的具体机制是什么,另有文章阐述)

二、比nestjs更优雅的ts控制反转策略

基于TS的后端框架一般都会提供依赖容器,实现控制反转。控制反转有两种策略:依赖注入依赖查找 。CabloyJS5.0同时支持依赖注入依赖查找 ,并且通过模块范围的辅助,让依赖查找的代码更加简洁高效,下面挑几个特性举例说明:

  1. Service服务
  2. Config配置
  3. 多语言
  4. 错误异常

三、Service服务

1. 创建一个Service

在CabloyJS中,local bean相当于nestjs中service的概念,下面创建一个local bean

javascript 复制代码
import { BeanBase, Local } from '@cabloy/core';
import { ScopeModule } from '../resource/this.js';

@Local()
export class LocalHome extends BeanBase<ScopeModule> {
  async echo({ user: _user }) {
    return `Hello World!`;
  }
}
  1. 通过@Local声明LocalHome是一个local bean

  2. LocalHome继承自基类BeanBase

2. Service的依赖注入

接下来,在Controller中采用依赖注入的方式来使用LocalHome

javascript 复制代码
import { BeanBase, Controller, Use } from '@cabloy/core';
import { ScopeModule } from '../resource/this.js';
import { LocalHome } from '../local/home.js';

@Controller()
export class ControllerHome extends BeanBase<ScopeModule> {
  @Use()
  home: LocalHome;

  async echo() {
    const res = await this.home.echo({
      user: this.ctx.state.user.op,
    });
    this.ctx.success(res);
  }
}
  1. 使用@Use注入LocalHome

3. Service的依赖查找

接下来,在Controller中采用依赖查找的方式来使用LocalHome

javascript 复制代码
import { BeanBase, Controller } from '@cabloy/core';
import { ScopeModule } from '../resource/this.js';

@Controller()
export class ControllerHome extends BeanBase<ScopeModule> {
  async echo() {
    const res = await this.scope.local.home.echo({
      user: this.ctx.state.user.op,
    });
    this.ctx.success(res);
  }
}
  1. 不需要导入LocalHome,直接在代码中使用this.scope.local来访问容器中的local bean实例

看一下动画演示,提供了完整的类型智能提示:

四、Config配置

1. 定义Config

可以为业务模块单独定义一些Config配置,如下:

diff 复制代码
import { CabloyApplication } from '@cabloy/core';

export const config = (_app: CabloyApplication) => {
  return {
+   prompt: 'hello world',
  };
};

2. 使用Config

可以在LocalHome中直接使用刚才定义的config

diff 复制代码
import { BeanBase, Local } from '@cabloy/core';
import { ScopeModule } from '../resource/this.js';

@Local()
export class LocalHome extends BeanBase<ScopeModule> {
  async echo({ user: _user }) {
+   return this.scope.config.prompt;
-   return `Hello World!`;
  }
}
  1. 不需要导入任何类型,直接在代码中使用this.scope.config来访问当前业务模块中的config配置

看一下动画演示,提供了完整的类型智能提示:

五、多语言

1. 定义语言资源

可以为业务模块定义语言资源,比如,这里分别定义英文和中文两种语言资源

英文

javascript 复制代码
export default {
  HelloWorld: 'Hello World',
};

中文

javascript 复制代码
export default {
  HelloWorld: '您好世界',
};

2. 使用语言资源

可以在LocalHome中直接使用刚才定义的语言资源

diff 复制代码
import { BeanBase, Local } from '@cabloy/core';
import { ScopeModule } from '../resource/this.js';

@Local()
export class LocalHome extends BeanBase<ScopeModule> {
  async action({ user: _user }) {
+   // 自动判断当前语言
+   const message = this.scope.locale.HelloWorld();
+   // 强制使用英文资源
+   const message1 = this.scope.locale.HelloWorld.locale('en-us');
+   // 强制使用中文资源
+   const message2 = this.scope.locale.HelloWorld.locale('zh-cn');
+   return `${message}:${message1}:${message2}`;
-   return this.scope.config.prompt;
  }
}
  1. 不需要导入任何类型,直接在代码中使用this.scope.locale来访问当前业务模块中的语言资源

看一下动画演示,提供了完整的类型智能提示:

六、错误异常

1. 定义错误码

可以为业务模块定义错误码

diff 复制代码
export enum Errors {
+ Error001 = 1001,
}
  1. 这里定义了一个错误枚举类型Error001,对应的错误码是1001

2. 定义错误码对应的语言资源

可以为错误码定义语言资源,比如,这里分别定义英文和中文两种语言资源

英文

diff 复制代码
export default {
+ Error001: 'This is a test',
  HelloWorld: 'Hello World',
};

中文

diff 复制代码
export default {
+ Error001: '这是一个错误',
  HelloWorld: 'Hello World',
};

3. 抛出错误异常

可以在LocalHome中直接使用刚才定义的错误枚举值,并抛出异常

diff 复制代码
import { ScopeModule } from '../resource/this.js';

@Local()
export class LocalHome extends BeanBase<ScopeModule> {
  async action({ user: _user }) {
+   // 直接抛出异常
+   this.scope.error.Error001.throw();
-   return this.scope.config.prompt;
  }
}
  1. 不需要导入任何类型,直接在代码中使用this.scope.error来访问当前业务模块中的错误枚举值

看一下动画演示,提供了完整的类型智能提示:

六、后记

Cabloy4.0中就已经提供了大量业务能力,比如:工作流引擎、表单引擎、权限引擎、字段权限、多级缓存、模块化体系、分布式架构、多租户引擎,等等。随着Cabloy5.0 Typescript的赋能,这些业务能力也随之有了全新的表现

欲了解更多,请关注每晚8点B站直播:濮水代码

相关推荐
尾善爱看海7 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
驳是8 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea8 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持8 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者9 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn9 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
计算机魔术师11 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端
计算机魔术师11 小时前
OpenAI的AI代理偷偷给RubyGems下毒,我们却毫无察觉
前端
甲维斯11 小时前
0代码,0建模,3句话开发一个3D游戏!
前端·游戏·游戏开发
IT_陈寒11 小时前
Vue的响应式更新把我坑惨了,原来问题出在这
前端·人工智能·后端