🌲 新订年付会员,赠送一年会员资格。立即订阅

博客

自学开发服务端应用(基于 Nest.js 框架)

服务端应用就是在服务器上边儿运行的应用程序,服务端应用的主要作用就是为其它的应用提供各种服务,比如给前端、移动端、桌面端应用提供数据处理、身份验证等服务。前端、移动端这些端都可以统称为客户端,或者叫用户端,因为应用最终都是在这些端上被用户使用的。

如果你想独立完成一个完整的应用,你需要学会开发应用的服务端,也要开发应用的客户端。服务端应用可以给多种不同类型的客户端提供服务,也就是你的前端与移动端应用都可以使用同一个服务端应用提供的服务。

开发服务端应用有很多选择,可以使用不同类型的程序语言或应用框架。运行服务端应用的服务器上都要配置好一个运行环境,我们开发的应用会在这个环境上运行。有了正确的环境,应用才能正常运行。比如你打算用 JavaScript 语言创建服务端应用,你需要在服务器上安装一个 Node.js。

基本概念

客户端与服务端一般会通过请求与响应的方式进行沟通。客户端通过网络对服务端发出请求,服务端得到了请求,会做出对应的响应。比如用户在客户端上输入了用户名与密码,点击了登录按钮以后,会发出一个登录请求,服务器收到请求可以验证请求登录的用户,如果一切正常就让这个用户登录。

MasterClass 的故事:如何说服顶级大师讲课

大卫走进老板的办公室,“麦克,我不想干了,我想出去创造点什么”。大卫有一头小卷发,说话有一点结巴,30 左右的样子,当时他在一家风投公司工作。男人在 25 - 30 岁之间都会有这么一次冲动,都想出去创造点什么。

麦克:你想出去干点啥呢,先跟我说说。大卫:我也不知道,有几个想法,不过还不确定。麦克:需要多少钱?大卫:25 万左右。麦克没作声,随手写了一张 50 万的支票,递给了大卫。“大卫,这里有 50 万,你回去好好想想到底要干点啥。”

大卫接过支票,走出老板的办公室,给他妈打了个电话。大卫妈:What?你老板是不是傻子,你没想法,没团队,什么都没有,他为什么要给你钱。大卫:妈,因为他相信你的儿子。其实大卫当时也有点害怕,他知道这种事情人生也只会发生这么一次。

大卫回家以后开始思考到底要创造点什么,思考项目的前景,是否可持续,是否能做大。后来一位朋友的话让他转变了思考的方向。朋友说:别扯那么多了,这么招,你就做一件事情,这件事情即使失败,你也不后悔做就行了。这句话点醒了他,最终确定要做跟教育相关的事情,这其实跟他童年的记忆也有点关系。

Nest.js:WebSockets(文档)

Gateway 是用@WebSocketGateway() 装饰的类。Gateway 的内部使用了 socket.io,不过你也可以使用其它的库,比如原生的 Web sockets。Gateway 就像是一个简单的 provider,你可以通过构造方法给它注入依赖,你也可以在其它的类里面注入使用 gateway 。

安装

先得安装需要的包:

npm install @nestjs/websockets @nestjs/platform-socket.io --save
npm install @types/socket.io --save-dev

预览

一般情况下,每个 gateway 监听的端口跟 HTTP 服务器用的端口一样,除非你的应用不是一个 Web 应用,或者你修改了端口。你可以给 @WebSocketGateway 装饰器提供一个参数,比如 @WebSocketGateway(80),这里的 80 就是选择使用的端口。你还可以设置 gateway 使用的 namespace 。

Nest.js:配置(文档)

应用都会在多种环境中运行,根据不同的环境,应用可能需要使用不同的配置。比如应用在本地与生产环境可能会使用不同的数据库配置信息。用 .env 文件可以实现。我们可以创建一个 ConfigModule  配置,里面有个 ConfigService 服务,用它加载配置的值。

安装

一些平台会自动把环境变量附加到 process.env 全局。不过在本地环境上我们得手工处理一下,解析环境变量文件可以使用 dotenv 这个包。

npm install dotenv --save
npm insatll @types/dotenv --save-dev

服务

先创建一个 ConfigService 类。

Nest.js:Serialization(文档)

Serializer 提供了在返回响应之前的数据处理功能。比如像用户密码这种敏感数据不应该包含在响应里。一些属性可能需要转换一下。响应的实体数据可以只包含指定的属性,比如 id 还有 name。

Nest 提供的 ClassSerializerInterceptor 可以帮我们做这些事情,它用了 class-transformer 包提供的功能。ClassSerializerInterceptor 拿到方法返回的值以后会交给 class-transformer 包里提供的 classToPlain 方法。

排除属性

比如在实体里排除 password 属性:

import { Exclude } from 'class-transformer';

export class UserEntity {
  id: number;
  firstName: string;
  lastName: string;

  @Exclude()
  password: string;
}

使用:

Nest.js:测试(文档)

自动化测试是软件开发的基础,至少测试要覆盖到系统里的一些比较敏感的部分。我们需要使用不同类型的测试,比如集成测试、单元测试、e2e 测试等等,Nest 提供了一些工具可以改善创建这些测试的体验,默认集成了 Jest 测试框架,你也可以使用自己熟悉的测试框架。

安装

先得安装需要的包:

npm install @nestjs/testing --save-dev

单元测试

Unit testing,单元测试。Jest 是一个非常成熟的测试框架,框架可以用来运行测试,里面也提供了 assert 函数,测试替身,可以用来 mocking 或 spying 等等。

假设应用里有两个类:CatsController 与 CatsService。下面我们手工强制让调用 catsService.findAll() 方法的时候返回 result,这样我们就可以测试 catsController.findAll() 方法是否可以返回我们期望的结果了。

Nest.js:自定义 Provider(文档)

很多时候我们需要直接往 Nest 的 Ioc(Inversion of control)  容器里绑定点东西。比如,一些 constant 值,基于当前环境创建的配置对象,外部库,或者根据一些其它定义的 provider 提前算好的值等等。而且你还可以覆盖实施,比如使用不同的类,需要时还可以使用各种测试替身。

要注意一件非常重要的事情,就是 Nest 会使用 token 来确定依赖。一般这个自动生成的 token 就是类。如果你要创建自定义的 provider,你得自个儿选择一个 token。大部分情况这个 token 都可以使用字符串或 symbol 表示。最好你可以在单独的文件里存储这些 token,比如放在一个 constants.ts 文件里。下面是一些可用的选项。

使用值

定义 constant 值,把外部库放到 Nest 容器里,或者使用 mock 对象替换真实的实施,这些情况都可以用 useValue 这种用法。

TypeScript:理解 Reflect Metadata

在定义类或者类方法的时候,可以设置一些元数据,我们可以获取到在类与类方法上添加的元数据,用的方法就是 Reflect Metadata。元数据指的是描述东西时用的数据。

在 TypeScript 里使用 Reflect Metadata 需要做下面这样的配置:

{
  "compilerOptions": {
    "experimentalDecorators": true ,
    "emitDecoratorMetadata": true
  },
}

然后在项目里安装 reflect-metadata 这个包:

npm install reflect-metadata --save

然后做个实验:

JavaScript:理解属性描述器(Property Descriptor)

一个 JavaScript 对象里面可能有一堆属性,属性都有一个名字,还有对应的值,除了这些其实还隐含了一些东西,这就是 Property Descriptor。来做个实验:

const user = {
  name: 'ninghao',
};

const descriptor = Object.getOwnPropertyDescriptor(user, 'name');

console.log(descriptor);

上面定义了一个叫 user 的对象,里面只有一个属性叫 name,对应的值是个字符串 ninghao。如果要检查一下 name 这个属性的 Descriptor,可以使用 Object 上的 getOwnProperyDescriptor 方法,把对象还有对象的属性交给这个方法就可以了。

执行上面的代码,会返回:

TypeScript:理解 Decorator 装饰器

Decorator 装饰器,在 TypeScript 里装饰器就是函数,装饰器可以装饰类,类的属性、方法还有方法的参数等等。装饰器可以处理它装饰的东西,比如给它装饰的东西添加点额外的东西或者修改或替换它装饰的东西。在 Nest.js 应用框架里大量地使用了装饰器。

定义类装饰器

类装饰器就是装饰类用的装饰器,这种装饰器接收一个构造方法参数。

function log(target: any) {
  console.log('hello ~', target);
}

log 其实就是一个函数,只不过根据装饰器要装饰的东西的不同,装饰器函数接收的参数会有一些不同。比如我们这个 log 要装饰类,也就是它是一个类装饰器,那它接收的这个 target 参数就是类的构造方法。log 目前的作用就是在代码运行的时候输出一个 hello,后面加上它接收的 target 参数的值。



微信好友

用微信扫描二维码,
加我好友。



微信公众号

用微信扫描二维码,
订阅宁皓网公众号。



240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

11635
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点