比 Nest.js 更优雅的 TS 控制反转策略 - 依赖查找

2024-04-08 17:44

本文主要是介绍比 Nest.js 更优雅的 TS 控制反转策略 - 依赖查找,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、Cabloy5.0 内测预告

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

1. 新旧技术栈对比:

后端前端
旧版js、egg2.0、mysqljs、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

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

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

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 配置,如下:

import { CabloyApplication } from '@cabloy/core';export const config = (_app: CabloyApplication) => {return {
+   prompt: 'hello world',};
};

2. 使用 Config

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

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. 定义语言资源

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

英文

export default {HelloWorld: 'Hello World',
};

中文

export default {HelloWorld: '您好世界',
};

2. 使用语言资源

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

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. 定义错误码

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

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

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

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

英文

export default {
+ Error001: 'This is a test',HelloWorld: 'Hello World',
};

中文

export default {
+ Error001: '这是一个错误',HelloWorld: 'Hello World',
};

3. 抛出错误异常

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

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 来访问当前业务模块中的错误枚举值

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

这篇关于比 Nest.js 更优雅的 TS 控制反转策略 - 依赖查找的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/886181

相关文章

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

使用DrissionPage控制360浏览器的完美解决方案

《使用DrissionPage控制360浏览器的完美解决方案》在网页自动化领域,经常遇到需要保持登录状态、保留Cookie等场景,今天要分享的方案可以完美解决这个问题:使用DrissionPage直接... 目录完整代码引言为什么要使用已有用户数据?核心代码实现1. 导入必要模块2. 关键配置(重点!)3.

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

Java反转字符串的五种方法总结

《Java反转字符串的五种方法总结》:本文主要介绍五种在Java中反转字符串的方法,包括使用StringBuilder的reverse()方法、字符数组、自定义StringBuilder方法、直接... 目录前言方法一:使用StringBuilder的reverse()方法方法二:使用字符数组方法三:使用自

Windows系统下如何查找JDK的安装路径

《Windows系统下如何查找JDK的安装路径》:本文主要介绍Windows系统下如何查找JDK的安装路径,文中介绍了三种方法,分别是通过命令行检查、使用verbose选项查找jre目录、以及查看... 目录一、确认是否安装了JDK二、查找路径三、另外一种方式如果很久之前安装了JDK,或者在别人的电脑上,想

Spring Security注解方式权限控制过程

《SpringSecurity注解方式权限控制过程》:本文主要介绍SpringSecurity注解方式权限控制过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、摘要二、实现步骤2.1 在配置类中添加权限注解的支持2.2 创建Controller类2.3 Us