Nest.js 控制器与服务,告诉你什么是依赖注入

先前用Nest.js写了一个crud demo,为了更加深入的去学习nest.js,还是要把官方文档走一遍的,今天就先看看控制器,服务和module。

目录

控制器

.env

提供者

依赖注入


控制器

控制器可以说是上一个nest.js项目用的最多的一部分了,很多东西我们已经见过了,那这个例子来说:

@Get('ab*cd')
@HttpCode(204)
@Header('Cache-Control', 'none')
findAll() {
  return 'This route uses a wildcard';
}

我们已经知道了@Get,这里也一样,*代表通配符,使用正则来定义路由,然后是@HttpCode来添加任意状态码,@Header来定义响应头。

下面这个demo是关于动态路由和拿到动态路由参数的方法:

@Get(':id')
findOne(@Param('id') id): string {
  return `This action returns a #${id} cat`;
}

':id'是我们定义动态路由的方法,我们在这里拿到了标记的ID值,同时还把ID通过@Param的方式赋予给了id这个变量。同时我们要注意,这个:id的动态特性是可选的,也就是说我们如果有不需要ID的动态请求,一定要把哪个请求放在这个ID的前面,否则哪个请求可能永远都不会执行。

关于数据对象模型,我们在demo中其实有好好讲过了,这里不再重复,应该知道这是接受客户端参数的工具.

.env

讲到这儿,控制器的东西其实说的差不多了,讲一个之前做小demo一直没注意到的一个东西,就是一些常量,或者是环境变量的问题.

我们可以通过安装:“dotenv”的方式来配置:

$ npm i --save dotenv

在根目录下创建.env,写入我们想要的常量,比如端口:

PORT=3000
import 'dotenv/config'
...
const port = process.env.PORT
...
  await app.listen(port);

同时还有个小问题就是我们的运行日志上看不到在哪个端口运行的,我们可以通过添加Logger输出:

....
[Nest] 12028   - 2019-10-01 6:34:18 PM  
 [RouterExplorer] Mapped {/:id, PUT} route +4ms
[Nest] 12028   - 2019-10-01 6:34:18 PM  
 [RouterExplorer] Mapped {/:id, DELETE} 
route +30ms
[Nest] 12028   - 2019-10-01 6:34:18 PM  
 [RoutesResolver] InstgramController {/instgram}: +3ms
[Nest] 12028   - 2019-10-01 6:34:18 PM  
 [RouterExplorer] Mapped {/, GET} route 
+16ms
[Nest] 12028   - 2019-10-01 6:34:18 PM  
 [NestApplication] Nest application successfully started +134ms
[Nest] 12028   - 2019-10-01 6:34:18 PM  
 App run in http://localhost:3000 +59ms

提供者

这个翻译的名字是有点别扭的,但其实也很好懂:

提供者是纯粹的 JavaScript 类,其上方有 @Injectable() 装饰器

比如我们demo中的service:
 

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

 可以看触,其实provider/service和chontroller都是不难理解的,如果你觉得难的话,那么问题可能就集中在一个东西上了:"Injectable()"

依赖注入

因为这个设计模式的大火是从angular开始的,所以我们用angular的代码来分析一下,不会angular?别着急,我也不会,但是代码还是很简单的。

export class Car {

  public engine: Engine;
  public tires: Tires;
  public description = 'No DI';

  constructor() {
    this.engine = new Engine();
    this.tires = new Tires();
  }

  // Method using the engine and tires
  drive() {
    return `${this.description} car with ` +
      `${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
  }
}

这段代码是没有依赖注入的,那么这段代码有什么问题呢?大家主要看constructor函数上,可以看到:

Car 类需要一个引擎 (engine) 和一些轮胎 (tire),它没有去请求现成的实例, 而是在构造函数中用具体的 EngineTires 类实例化出自己的副本

但如果我们的引擎类升级了,需要传递一个参数应该怎么办呢?

没办法,我们在重新创建engine的构建函数,这样带来的坏处就是car类被我们破坏了,这样让car类显得十分脆弱。那么有什么办法克服呢?

public description = 'DI';

constructor(public engine: Engine, public tires: Tires) { }

 如果我们这样写的话会发生什么呢?其实这里借助 TypeScript 的构造器语法来同时定义参数和属性,而car类里面不需要再重新创建engine等类。

依赖注入其实就是这么个到里,让类从外部源中获得它的依赖,而不必亲自创建它们。

但是这样做的话,使用者会加大了很多工作量,因为他们要必须创建所有这三部分了:CarEngineTires。

这时候我们需要一个大类来处理这三个类:

import { Engine, Tires, Car } from './car';

// BAD pattern!
export class CarFactory {
  createCar() {
    let car = new Car(this.createEngine(), this.createTires());
    car.description = 'Factory';
    return car;
  }

  createEngine() {
    return new Engine();
  }

  createTires() {
    return new Tires();
  }
}

但这样的话也有一个问题,当方法变得更多时,这里的依赖关系会变成一团乱麻。这时注入器就可以发挥其作用了: 

let car = injector.get(Car);

具体的实现大家可以继续学习angular,这里的injectable就是这个原理。

你可能感兴趣的:(Nest.js学习日记)