NestJs + TypeOrm + Ant Design Pro 搭建股票估值查询系统(一)

传送门
本章内容
  1. Nest安装与错误处理
  2. 自定义数据返回格式
  3. 自定义异常处理、错误码
安装

请确保操作系统上安装了 Node.js(>= 10.13.0)

本地环境

$ node -v
v14.15.4
$ npm -v
6.14.11

安装Nest CLI

$ npm i -g @nestjs/cli 

初始化项目

$ nest new project-name

将创建 project-name 目录, 安装node模块和一些其他样板文件,并将创建一个 src 目录,目录中包含几个核心文件

src
├── app.controller.ts
├── app.module.ts
└── main.ts

运行项目

$ npm run start

神奇的事情发生了,迎面就是一堆错误

在这里插入图片描述
遇到错误不要慌,交友网站搜一搜:./node_modules/tapable,哟呵,还是热乎的
在这里插入图片描述
大意是tapable这个库更新了,相关webpack版本也升级了,吧啦吧…好歹找到了解决方案(原文链接:github
在这里插入图片描述

命令走一个

$ npm i @types/webpack@4.41.27
$ npm i tapable@1.1.3

再次运行启动成功,浏览器中输入:http://localhost:3000/

在这里插入图片描述

久违的hello world!迷人依旧!

用户模块

不管业务需求是啥,先来个用户模块错不了,src目录下创建文件夹modules,使用Nest CLI生成一个user模块,控制器以及service

$ nest g mo modules/user
$ nest g co modules/user
$ nest g s modules/user

user.controller.ts写入如下代码

import { Controller, Get } from '@nestjs/common';

@Controller('user')
export class UserController {
  @Get('sayhi')
  async sayhi(): Promise<string> {
    return '你好,世界';
  }
}

重新运行项目,使用api调试工具访问:http://localhost:3000/user/sayhi,符合我们的预期

在这里插入图片描述

数据格式

实际项目中,api接口返回的一般都是固定结构的json对象,类似

{
    "code":0,
    "msg":"success",
    "data":{
			...
    }
}

其中code为自定义的业务错误码,比如没有权限,注册时用户名已注册等,src目录下创建libs文件夹,创建一个拦截器

$ nest g in libs/interceptors/data

拦截器代码

import {
  Injectable,
  NestInterceptor,
  CallHandler,
  ExecutionContext,
} from '@nestjs/common';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
interface Response<T> {
  data: T;
}
@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    next: CallHandler<T>,
  ): Observable<Response<T>> {
    return next.handle().pipe(
      map((data) => {
        return {
          data: data ?? null,
          code: 0,
          message: 'success',
        };
      }),
    );
  }
}

main.ts中全局注册

import { NestFactory } from '@nestjs/core';
import { TransformInterceptor } from './libs/interceptors/data.interceptor';
import { AppModule } from './app.module';

async function bootstrap() {
  ...
  app.useGlobalInterceptors(new TransformInterceptor());
  ...
}
bootstrap();

运行程序,再次访问:http://localhost:3000/user/sayhi

{
    "data": "你好,世界",
    "code": 0,
    "message": "success"
}
自定义异常

实际项目中,很多情况下我们需要中断程序运行,返回错误信息,创建一个过滤器

$ nest g f libs/filters/http-exception

src/libs目录下创建enums目录,新建error-code-enum.ts文件,放几个错误码

export enum BusiErrorCode {
  TIMEOUT = -1, // 系统繁忙
  SUCCESS = 0, // 成功
  PARAM_ERROR = 10000, // 请求参数错误
  NOT_FOUND = 10001, // 查找的资源不存在
  UN_AUTHORIZED = 20000, // 用户未登录
  AUTH_FORBIDDEN = 30000, // 用户没有权限
  PWD_ERROR = 40000, // 账号或者密码错误
}

libs/filters目录下创建busi.exception.ts文件

import { HttpException, HttpStatus } from '@nestjs/common';
import { BusiErrorCode } from '../enums/error-code-enum';

export class BusiException extends HttpException {
  private _code: BusiErrorCode;
  private _message: string;
  constructor(
    code: BusiErrorCode | number,
    message: string,
    statusCode: HttpStatus = HttpStatus.BAD_REQUEST,
  ) {
    super(message, statusCode);
    this._code = code;
    this._message = message;
  }

  getErrorCode(): BusiErrorCode {
    return this._code;
  }

  getErrorMessage(): string {
    return this._message;
  }
}

http-exception.filter.ts文件中代码

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
} from '@nestjs/common';
import { BusiException } from './busi.exception';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();

    let code, message;
    if (exception instanceof BusiException) {
      code = exception.getErrorCode();
      message = exception.getErrorMessage();
    } else {
      code = exception.getStatus();
      message = exception.message;
    }
    response.status(status).json({
      code,
      message,
      data: null,
      date: new Date().toLocaleDateString(),
      path: request.url,
    });
  }
}

main.ts中全局注册

import { NestFactory } from '@nestjs/core';
import { TransformInterceptor } from './libs/interceptors/data.interceptor';
import { AppModule } from './app.module';

async function bootstrap() {
  ...
  app.useGlobalFilters(new HttpExceptionFilter());
  ...
}
bootstrap();

修改user.controller.ts,加入触发异常的代码

import { Controller, Get, HttpStatus } from '@nestjs/common';
import { BusiException } from '../../libs/filters/busi.exception';
import { BusiErrorCode } from '../../libs/enums/error-code-enum';

@Controller('user')
export class UserController {
  ...
  @Get('exception')
  async exception(): Promise<string> {
    // throw new BusiException(BusiErrorCode.NOT_FOUND, '缺省状态码,默认触发http 400错误');
    throw new BusiException(
      BusiErrorCode.NOT_FOUND,
      '错误:http状态正常',
      HttpStatus.OK,
    );
  }
}

运行程序,访问:http://localhost:3000/user/exception
在这里插入图片描述

看起来还不错,下篇我们捣鼓TypeOrm和MySQL数据库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值