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')
  }
}
相关推荐
_jiang2 天前
nestjs 入门实战最强篇
redis·typescript·nestjs
敲代码的彭于晏5 天前
【Nest.js 10】JWT+Redis实现登录互踢
前端·后端·nestjs
前端小王hs18 天前
Nest通用工具函数执行顺序
javascript·后端·nestjs
明远湖之鱼20 天前
从入门到入门学习NestJS
前端·后端·nestjs
吃葡萄不吐番茄皮22 天前
从零开始学 NestJS(一):为什么要学习 Nest
前端·nestjs
东方小月23 天前
Vue3+NestJS实现权限管理系统(六):接口按钮权限控制
前端·后端·nestjs
白雾茫茫丶1 个月前
Nest.js 实战 (十四):如何获取客户端真实 IP
nginx·nestjs
Spirited_Away1 个月前
Nest世界中的AOP
前端·node.js·nestjs
Eric_见嘉1 个月前
NestJS 🧑‍🍳 厨子必修课(六):Prisma 集成(下)
前端·后端·nestjs
kongxx2 个月前
NestJS中使用Guard实现路由保护
nestjs