nestjs基础知识之1控制反转、装饰器

控制反转IOC 依赖注入DI

控制反转IOC:高层模块不应该依赖底层模块,二者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象

依赖注入DI:和IOC是同根生,两个本来是一个东西,只不过由于控制反转概念比较含糊,(可能只是理解为容器控制对象,很难让人想到谁来维护对象关系),2004年Martin Fowler又给出了一个新的名字:依赖注入,类A依赖类B的常规表现是在A中使用B的实例。

依赖注入就是将B的实例注入到A中,这样A就不需要知道如何创建B的实例了,而是由外部来决定B的实例,这样就降低了类之间的耦合度,也降低了类之间的依赖关系,所以依赖注入是控制反转的一种实现方式,而控制反转是一种设计模式,依赖注入是一种实现方式

  • 未使用控制反转、依赖注入的代码:
typescript 复制代码
⭕️未使用

class A {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
 
 
class B {
    age:number
    entity:A
    constructor (age:number) {
        this.age = age;
        this.entity = new A('小满')
    }
}
 
const c = new B(18)
 
c.entity.name

B 中代码的实现是需要依赖 A 的,两者的代码耦合度非常高。 当两者之间的业务逻辑复杂程度增加的情况下,维护成本与代码可读性都会随着增加,并且很难再多引入额外的模块进行功能拓展。

  • 使用IOC容器依赖注入
typescript 复制代码
class A1 {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
 
 
class C1 {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
//中间件用于解耦
class Container {
    modeuls: any
    constructor() {
        this.modeuls = {}
    }
    provide(key: string, modeuls: any) {
        this.modeuls[key] = modeuls
    }
    get(key) {
        return this.modeuls[key]
    }
}
 
const mo = new Container()
mo.provide('a', new A1('小满1'))
mo.provide('c', new C1('小满2'))
 
class B1 {
    a: any
    c: any
    constructor(container: Container) {
        this.a = container.get('a')
        this.c = container.get('c')
    }
}
 
new B1(mo)

在引入IoC容器container之后,B与A的代码逻辑已经解耦,可以单独拓展其他功能,也可以方便地加入其他模块C。所以在面对复杂的后端业务逻辑中,引入IoC可以降低组件之间的耦合度,实现系统各层之间的解耦,减少维护与理解成本。

装饰器

需要开启装饰器: tsc --init 生成tsconfig.json文件,配置

{ 复制代码
    "compilerOptions": {
      "experimentalDecorators": true,
    }
  }
  

类装饰器 ClassDecorator

主要是通过@符号添加装饰器

他会自动把class的构造函数传入到装饰器的第一个参数 target

然后通过prototype可以自定义添加属性和方法

typescript 复制代码
let decotators: ClassDecorator = (target:any) =>{
    target.prototype.name = 'jack'
}
// @decotators是一个语法糖,本质上是一个函数,可以通过decotators(DOCA)直接使用
@decotators
class DOCA {
    constructor () {
    }
 
}
const a:any = new DOCA()

属性装饰器PropertyDecorator

使用@符号给属性添加装饰器

他会返回两个参数给属性装饰器PropertyDecorator

1.原形对象

2.属性的名称

typescript 复制代码
const currency: PropertyDecorator = (target: any, key: string | symbol) => {
    console.log(target, key) // 输入两次:target是类,key是属性名docb_name1、docb_name2
}
 
 
class DOCB {
    @currency
    public docb_name1: string
    @currency
    public docb_name2: string
    constructor() {
        this.docb_name1 = 'jackb1'
        this.docb_name2 = 'jackb2'
    }
    getName() {
        return this.docb_name1
    }
}

方法装饰器

使用@符号给方法添加装饰器

返回3个参数

1.原形对象

2.方法的名称

3.该方法的属性描述符 可写对应writable,可枚举对应enumerable,可配置对应configurable

typescript 复制代码
const docM: MethodDecorator = (target: any, key: string | symbol,descriptor:any) => {
    console.log(target, key,descriptor) 
/*      
    target类的原型对象, 方法名getName, 方法getName的属性描述符{
        value: [Function (anonymous)],
        writable: true,
        enumerable: true,
        configurable: true
      }
 */

}
 
class DOCD {
    public name: string
    constructor() {
        this.name = ''
    }
    @docM
    getName(name:string,age:number) {
        return this.name
    }
}

参数装饰器

使用@符号给属性添加装饰器

他会返回两个参数给装饰器

1.原形对象

2.方法的名称

3.参数的位置从0开始

typescript 复制代码
const docP: ParameterDecorator = (target: any, key: string | symbol, index: number) => {
  console.log(target, key, index) // target类的原型对象, 方法名getName, age参数的index位置1
}

class DOCC {
  public name: string
  constructor() {
    this.name = ''
  }
  getName(name: string, @docP age: number) {
    return this.name
  }
}

实现一个GET装饰器请求

typescript 复制代码
import axios from 'axios'

/* 
      定义装饰器,这里需要实现装饰器工厂接收装饰器传入的参数,如url
*/
const GET = (url: string): MethodDecorator => {
  return (target, propertyName, descriptor) => {
    // 获取当前使用装饰器的函数
    const fnc: any = descriptor.value
    axios
      .get(url)
      .then((res) => {
        // 把axios的结果返回给当前使用装饰器的函数
        fnc(res, { status: 200 })
      })
      .catch((err) => {
        fnc(err, { status: 404 })
      })
  }
}

// 定义控制器
class MyGetController {
  constructor() {}

  // 把getList方法放到GET装饰器里面回调执行
  @GET('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
  getList(res, status) {
    // 获取axios返回的数据
    console.log(status, 'status')
    console.log(res.data.result.list, 'res')
  }
}
相关推荐
亮子AI4 天前
【NestJS】为什么return不返回客户端?
前端·javascript·git·nestjs
小p4 天前
nestjs学习2:利用typescript改写express服务
nestjs
Eric_见嘉10 天前
NestJS 🧑‍🍳 厨子必修课(九):API 文档 Swagger
前端·后端·nestjs
XiaoYu200218 天前
第3章 Nest.js拦截器
前端·ai编程·nestjs
XiaoYu200220 天前
第2章 Nest.js入门
前端·ai编程·nestjs
实习生小黄20 天前
NestJS 调试方案
后端·nestjs
当时只道寻常23 天前
NestJS 如何配置环境变量
nestjs
濮水大叔1 个月前
VonaJS是如何做到文件级别精确HMR(热更新)的?
typescript·node.js·nestjs
ovensi1 个月前
告别笨重的 ELK,拥抱轻量级 PLG:NestJS 日志监控实战指南
nestjs