Skip to content

createReactiveErrorManager

后端业务错误码管理系统,支持国际化和分类管理。

函数签名

typescript
function createReactiveErrorManager(
  config: ErrorManagerConfig,
  deps: ErrorManagerDeps
): ErrorManagerInstance

interface ErrorManagerConfig {
  defaultLocale: string
  fallbackLocale?: string
  categories: ErrorCategory[]
}

interface ErrorCategory {
  name: string
  prefix: string
  errors: ErrorCode[]
}

interface ErrorCode {
  code: string
  message: Record<string, string>
  httpStatus?: number
  level?: 'info' | 'warning' | 'error' | 'fatal'
  metadata?: Record<string, any>
}

class BusinessError extends Error {
  code: string
  httpStatus: number
  level: 'info' | 'warning' | 'error' | 'fatal'
  metadata: Record<string, any>
  params?: Record<string, any>
}

参数

参数名类型必填说明
configErrorManagerConfig错误管理器配置
config.defaultLocalestring默认语言
config.fallbackLocalestring回退语言
config.categoriesErrorCategory[]错误分类列表
depsErrorManagerDeps环境依赖

返回值

类型说明
ErrorManagerInstance错误管理器实例

工作原理

  1. 分类管理:按模块组织错误码(USER、ORDER、SYS等)
  2. 国际化:每个错误码支持多语言消息
  3. 参数化:支持 {key} 格式的参数替换
  4. 错误创建:提供 BusinessError 类封装错误信息
  5. 响应式:语言切换时自动更新

基础示例

typescript
import { createReactiveErrorManager } from 'zcw-shared/reactive/createReactiveErrorManager'
import { createReactive } from 'zcw-shared/reactive/createReactive'

const errorManager = createReactiveErrorManager({
  defaultLocale: 'zh-CN',
  fallbackLocale: 'en',
  categories: [
    {
      name: '用户相关',
      prefix: 'USER',
      errors: [
        {
          code: 'USER_NOT_FOUND',
          message: {
            'zh-CN': '用户不存在',
            'en': 'User not found'
          },
          httpStatus: 404,
          level: 'error'
        },
        {
          code: 'USER_ALREADY_EXISTS',
          message: {
            'zh-CN': '用户 {username} 已存在',
            'en': 'User {username} already exists'
          },
          httpStatus: 409
        }
      ]
    }
  ]
}, {
  createReactive,
  log: console.log,
  warn: console.warn
})

// 获取错误消息
const msg = errorManager.getMessage('USER_NOT_FOUND')
console.log(msg)  // '用户不存在'

// 带参数的消息
const msg2 = errorManager.getMessage('USER_ALREADY_EXISTS', { username: 'alice' })
console.log(msg2)  // '用户 alice 已存在'

// 创建错误
const error = errorManager.createError('USER_NOT_FOUND')
console.log(error instanceof BusinessError)  // true
console.log(error.code)  // 'USER_NOT_FOUND'
console.log(error.httpStatus)  // 404

// 抛出错误
try {
  errorManager.throwError('USER_NOT_FOUND')
} catch (e) {
  if (e instanceof BusinessError) {
    console.log(e.code, e.message, e.httpStatus)
  }
}

实际应用场景

Express/Koa 中间件

typescript
// 错误处理中间件
app.use((err, req, res, next) => {
  if (err instanceof BusinessError) {
    res.status(err.httpStatus).json({
      success: false,
      code: err.code,
      message: err.message,
      data: null
    })
  } else {
    res.status(500).json({
      success: false,
      code: 'SYS_INTERNAL_ERROR',
      message: '系统内部错误',
      data: null
    })
  }
})

// 使用示例
app.post('/api/users', async (req, res, next) => {
  try {
    const { username } = req.body
    const exists = await checkUserExists(username)
    
    if (exists) {
      errorManager.throwError('USER_ALREADY_EXISTS', { username })
    }
    
    // ...创建用户
  } catch (err) {
    next(err)
  }
})

微服务错误处理

typescript
// 定义错误码常量
export const ErrorCodes = {
  USER_NOT_FOUND: 'USER_NOT_FOUND',
  USER_UNAUTHORIZED: 'USER_UNAUTHORIZED',
  ORDER_NOT_FOUND: 'ORDER_NOT_FOUND'
} as const

// 在服务中使用
class UserService {
  async getUser(userId: string) {
    const user = await this.db.findUser(userId)
    
    if (!user) {
      throw errorManager.createError(ErrorCodes.USER_NOT_FOUND)
    }
    
    return user
  }
}

API 响应封装

typescript
interface ApiResponse<T = any> {
  success: boolean
  code: string
  message: string
  data: T | null
}

function successResponse<T>(data: T): ApiResponse<T> {
  return {
    success: true,
    code: 'SUCCESS',
    message: '操作成功',
    data
  }
}

function errorResponse(error: BusinessError): ApiResponse {
  return {
    success: false,
    code: error.code,
    message: error.message,
    data: null
  }
}

国际化支持

typescript
// 根据请求头切换语言
app.use((req, res, next) => {
  const locale = req.headers['accept-language']?.split(',')[0] || 'zh-CN'
  errorManager.setLocale(locale)
  next()
})

// 返回对应语言的错误消息
app.post('/api/login', (req, res) => {
  if (!validPassword) {
    const error = errorManager.createError('INVALID_PASSWORD', { minLength: 8 })
    return res.status(error.httpStatus).json(errorResponse(error))
  }
})

最佳实践

1. 错误码命名规范

typescript
// 格式:{模块前缀}_{描述}
USER_NOT_FOUND          // 用户模块
ORDER_CANCELLED         // 订单模块
SYS_INTERNAL_ERROR      // 系统模块
PAYMENT_FAILED          // 支付模块

2. 按模块组织

typescript
const categories = [
  { name: '用户模块', prefix: 'USER', errors: [...] },
  { name: '订单模块', prefix: 'ORDER', errors: [...] },
  { name: '支付模块', prefix: 'PAYMENT', errors: [...] },
  { name: '系统模块', prefix: 'SYS', errors: [...] }
]

3. HTTP 状态码映射

typescript
// 400 系列 - 客户端错误
{ code: 'INVALID_PARAMS', httpStatus: 400 }
{ code: 'USER_UNAUTHORIZED', httpStatus: 401 }
{ code: 'ACCESS_DENIED', httpStatus: 403 }
{ code: 'USER_NOT_FOUND', httpStatus: 404 }
{ code: 'USER_ALREADY_EXISTS', httpStatus: 409 }

// 500 系列 - 服务端错误
{ code: 'SYS_INTERNAL_ERROR', httpStatus: 500 }
{ code: 'SYS_SERVICE_UNAVAILABLE', httpStatus: 503 }

4. 错误级别使用

typescript
level: 'info'     // 信息,如订单已取消
level: 'warning'  // 警告,如库存不足
level: 'error'    // 错误,如用户不存在
level: 'fatal'    // 严重,如系统崩溃

统一的业务错误码管理,让后端开发更规范!