傳送門
- 線上示範 賬号:guest ,密碼:123456
- 源碼位址
本章内容
- Nest安裝與錯誤處理
- 自定義資料傳回格式
- 自定義異常處理、錯誤碼
安裝
請確定作業系統上安裝了 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/[email protected]
$ npm i [email protected]
再次運作啟動成功,浏覽器中輸入:
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資料庫。