在学习了一些设计模式以后,突然觉得很多知识都能够建立在这个基础体系下。也因此想再理解一下富有盛名的nestjs,正好有个项目感觉express写起来有点吃力了,计划将它升级成nest。
控制器
控制器负责处理传入的 请求 和向客户端返回 响应 。
控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。
为了创建一个基本的控制器,我们使用类和
装饰器。装饰器将类与所需的元数据相关联,并使Nest能够创建路由映射(将请求绑定到相应的控制器)。
首先说一下装饰器。装饰器是实现装饰者模式的一种方式,类似于我们在react中使用的HOC。其作用是对对象进行增强。装饰器不仅可以用于装饰函数,还可以用于装饰参数。
// nest
@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: Request): string {
return 'This action returns all cats';
}
}
我们来看看nest这段代码中几个装饰器。
-
Controller:类装饰器,在类声明之前被声明,应用于类构造函数,可以监视、增强、替换类的定义;
function Controller(prefixOrOptions) { const defaultPath = '/'; ... return (target) => { Reflect.defineMetadata(constants_1.PATH_METADATA, path, target); Reflect.defineMetadata(constants_1.HOST_METADATA, host, target); Reflect.defineMetadata(constants_1.SCOPE_OPTIONS_METADATA, scopeOptions, target); }; }以上这段代码节选了controller的源码,其中用到了 Reflect Metadata ,这是 ES7 的一个提案,它主要用来在声明的时候添加和读取元数据。
function classDecorator(): ClassDecorator { return target => { // 在类上定义元数据,key 为 `classMetaData`,value 为 `a` Reflect.defineMetadata('classMetaData', 'a', target); }; } function methodDecorator(): MethodDecorator { return (target, key, descriptor) => { // 在类的原型属性 'someMethod' 上定义元数据,key 为 `methodMetaData`,value 为 `b` Reflect.defineMetadata('methodMetaData', 'b', target, key); }; } @classDecorator() class SomeClass { @methodDecorator() someMethod() {} } Reflect.getMetadata('classMetaData', SomeClass); // 'a' Reflect.getMetadata('methodMetaData', new SomeClass(), 'someMethod'); // 'b' -
Get:方法装饰器
先大概看一下源码
const createMappingDecorator = (method) => (path) => { return exports.RequestMapping({ [constants_1.PATH_METADATA]: path, [constants_1.METHOD_METADATA]: method, }); }; const RequestMapping = (metadata = defaultMetadata) => { ... // 返回一个有三个参数的闭包函数 return (target, key, descriptor) => { Reflect.defineMetadata(constants_1.PATH_METADATA, path, descriptor.value); Reflect.defineMetadata(constants_1.METHOD_METADATA, requestMethod, descriptor.value); return descriptor; }; }; exports.Get = createMappingDecorator(request_method_enum_1.RequestMethod.GET);方法装饰器会在运行时传入3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象;
- 成员的名字;
- 成员的属性描述符;
-
Req:方法参数装饰器
参数装饰器表达式会在运行时被调用,可以为类的原型增加一些元素数据,传入3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象;
- 方法名称,如果装饰的是构造函数的参数,则值为
undefined - 参数在函数参数列表中的索引;