Exception
ℹ️
依赖版本:@artusx/core >= 1.1.0
ArtusX 提供了标准化异常处理能力,同时支持业务自定义。
框架规范
根据日常开发使用,对于异常返回的状态码,通常有两种处理方式:
- 根据标准规范,返回
status_code = 400 | 403 | 500
,以及错误信息 - 根据业务规范,返回
status_code = 200
,并在错误信息中,返回自定义错误码
框架中内置了三种 自定义异常 供业务使用:
- ArtusXStdError 标准异常,根据公共规范,返回状态码
- ArtusXBizError 业务异常,
status_code = 200
,在{ data, code }
中返回业务状态码 - ArtusXCustomError 自定义异常,
status_code
以及业务状态码,均由业务自行处理
异常定义
通过错误码,可用于规范团队 or 业务错误定义,在业务中通过 app.throwException(${CODE})
方式使用。
错误码
@artusx/core
已内置部分 code,可通过 HTTPErrorEnum
与 ArtusXErrorEnum
使用。
src/constants.ts
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
export enum HTTPErrorEnum {
// Status_Code = 400
HTTP_BAD_REQUEST = 'HTTP:BAD_REQUEST',
// Status_Code = 401
HTTP_UNAUTHORIZED = 'HTTP:UNAUTHORIZED',
// Status_Code = 403
HTTP_FORBIDDEN = 'HTTP:FORBIDDEN',
// Status_Code = 404
HTTP_NOT_FODUND = 'HTTP:NOT_FODUND',
// Status_Code = 405
HTTP_METHOD_NOT_ALLOWED = 'HTTP:METHOD_NOT_ALLOWED',
// Status_Code = 500
HTTP_INTERNAL_SERVER_ERROR = 'HTTP:INTERNAL_SERVER_ERROR',
// Status_Code = 501
HTTP_NOT_IMPLEMENTED = 'HTTP:NOT_IMPLEMENTED',
// Status_Code = 502
HTTP_BAD_GATEWAY = 'HTTP:BAD_GATEWAY',
// Status_Code = 503
HTTP_SERVICE_UNAVAILABLE = 'HTTP:SERVICE_UNAVAILABLE',
// Status_Code = 504
HTTP_GATEWAY_TIMEOUT = 'HTTP:GATEWAY_TIMEOUT',
}
export enum ArtusXErrorEnum {
// Status_Code = 500
ARTUSX_UNKNOWN_ERROR = 'ARTUSX:UNKNOWN_ERROR',
}
src/exception.json
{
"HTTP:BAD_REQUEST": {
"desc": "400",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:UNAUTHORIZED": {
"desc": "401",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:FORBIDDEN": {
"desc": "403",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:NOT_FODUND": {
"desc": "404",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:METHOD_NOT_ALLOWED": {
"desc": "405",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:INTERNAL_SERVER_ERROR": {
"desc": "500",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:NOT_IMPLEMENTED": {
"desc": "501",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:BAD_GATEWAY": {
"desc": "502",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:SERVICE_UNAVAILABLE": {
"desc": "503",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"HTTP:GATEWAY_TIMEOUT": {
"desc": "504",
"detailUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
},
"ARTUSX:UNKNOWN_ERROR": {
"desc": "500",
"detailUrl": "https://github.com/artusjs/artusx"
}
}
内置 Error
src/error.ts
export class ArtusXStdError extends Error {
name = 'ARTUSX_STD_ERROR';
data: any;
status: number;
constructor(status: number, message: string, data?: any) {
super(message);
this.data = data;
this.status = status;
}
}
export class ArtusXBizError extends Error {
name = 'ARTUSX_BIZ_ERROR';
data: any;
status: number; // 200
constructor(message: string, code: number, data?: any) {
super(message);
this.data = {
code,
data,
};
this.status = 200;
}
}
export class ArtusXCustomError extends Error {
name = 'ARTUSX_CUSTOM_ERROR';
data: any;
status: number;
constructor(status: number, message: string, code: number, data?: any) {
super(message);
this.data = {
code,
data,
};
this.status = status;
}
}
自定义 Error
src/error.ts
import { ArtusStdError } from '@artusx/core';
// 拓展错误码
export class ArtusXWrappedError extends ArtusStdError {
static code = 'ARTUSX:WRAPPED_ERROR';
name = 'ArtusXWrappedError';
constructor() {
super(ArtusXWrappedError.code);
}
}
// 自定义错误
export class BizCustomError extends Error {
name = 'BizCustomError';
}
异常捕获
捕获
exception filter 支持注解能力,可对捕获的错误进行统一的上报、记录等处理,支持如下异常捕获:
- 通用 Error
- 自定义 Error
- 框架 Error 拓展
- 错误码(框架内置)
- 自定义错误码(业务配置)
src/filter.ts
import { Catch, ArtusStdError, ArtusXExceptionFilterType, ArtusXContext } from '@artusx/core';
import { ArtusXWrappedError, BizCustomError } from './error';
@Catch()
export class DefaultExceptionHandler implements ArtusXExceptionFilterType {
async catch(_err: Error, _ctx: ArtusXContext) {
console.log('error:name', _err.name);
}
}
@Catch('BIZ:COMMON_ERROR')
export class AppCodeExceptionHandler implements ArtusXExceptionFilterType {
async catch(_err: ArtusStdError) {
console.log('error:code', _err.code);
}
}
@Catch(ArtusXWrappedError)
export class ArtusXWrapperExceptionHandler implements ArtusXExceptionFilterType {
async catch(_err: ArtusXWrappedError) {
console.log('error:code', _err.code);
}
}
@Catch(BizCustomError)
export class BizCustomExceptionHandler implements ArtusXExceptionFilterType {
async catch(_err: BizCustomError) {
console.log('error:name', _err.name);
}
}
抛出
示例演示了如何通过多种方式抛出异常。
src/exception-module/exception.controller.ts
import {
ArtusInjectEnum,
Inject,
GET,
Controller,
ArtusApplication,
ArtusXStdError,
} from '@artusx/core';
import type { ArtusXContext } from '@artusx/core';
import { ArtusXWrappedError, BizCustomError } from '../error';
@Controller('/exception')
export default class ExceptionController {
@Inject(ArtusInjectEnum.Application)
app: ArtusApplication;
@GET('/system_error')
async systemError(ctx: ArtusXContext) {
const passed = ctx.request.query?.passed;
if (!passed) {
this.app.throwException('ARTUSX:UNKNOWN_ERROR');
}
ctx.body = 'system_error';
}
@GET('/default_error')
async defaultError(ctx: ArtusXContext) {
const err = new Error('default error message');
err.name = 'default error';
if (err) {
throw err;
}
ctx.body = 'default_error';
}
@GET('/wrapper_error')
async wrapperError(ctx: ArtusXContext) {
const err = new ArtusXWrappedError();
if (err) {
throw err;
}
ctx.body = 'wrapper_error';
}
@GET('/std_error')
async stdError(ctx: ArtusXContext) {
const err = new ArtusXStdError(400, 'artusx std error', {
data: {},
});
if (err) {
throw err;
}
ctx.body = 'biz_custom_error';
}
@GET('/biz_common_error')
async commonError(ctx: ArtusXContext) {
const passed = ctx.request.query?.passed;
if (!passed) {
this.app.throwException('BIZ:COMMON_ERROR');
}
ctx.body = 'biz_common_error';
}
@GET('/biz_custom_error')
async customError(ctx: ArtusXContext) {
const err = new BizCustomError('biz custom error message');
if (err) {
throw err;
}
ctx.body = 'biz_custom_error';
}
}
配置
为了支持业务的自定义异常处理能力,框架支持通过配置方式,传递 ctx / error
,进而由业务自行进行异常上报,以及返回值配置。
src/config/config.default.ts
export default () => {
const artusx: ArtusXConfig = {
keys: 'artusx-koa',
port: 7001,
onError: async (ctx: ArtusXContext, error: ArtusXStdError) => {
// ctx.throw(error?.status || 500, error);
ctx.body = {
code: error.status || 500,
message: error.message,
};
ctx.status = 200;
},
};
};
异常列表
UNKNOWN_ERROR
未知错误,通常用于系统异常,返回 500
状态码。
{
"desc": "500",
"detailUrl": "https://artusjs.org/ecosystem/artusx/3.exception#unknown-error"
}