Skip to content

错误处理

所有请求 Promise rejection 都统一为 LuchRequestError。业务判断使用稳定的 code,不要匹配消息文本。

LuchRequestError

ts
class LuchRequestError<TConfig = unknown, TResponse = unknown> extends Error {
  constructor(
    message: string,
    code: LuchRequestErrorCode,
    options?: LuchRequestErrorOptions<TConfig, TResponse>
  )
}
成员说明
namemessagestack标准 Error 字段;name 固定为 LuchRequestError
code稳定的跨平台错误分类
config错误发生时管线使用的请求配置
task已创建时对应的原生 Task
responseHTTP 状态、响应转换或 interceptor 场景中的响应上下文
cause导致当前错误的底层异常或取消原因
raw未转换的平台原始错误或取消原因
cancelMode取消错误实际采用的 CancellationMode
isLuchRequestError固定为 true 的跨环境识别标记
toJSON()返回稳定摘要,不包含 Task 和完整 response

错误码常量

静态常量触发阶段主要区别
LuchRequestError.ERR_INVALID_CONFIG原生派发前配置无效或缺少对应 uni API,通常没有 response
LuchRequestError.ERR_NETWORKuni API 的 fail callbackrawcause 保留平台错误,不能证明服务端是否收到请求
LuchRequestError.ERR_BAD_STATUS收到原生响应后HTTP 状态未通过 validateStatus,保留完整 response
LuchRequestError.ERR_BAD_RESPONSE响应转换时响应无法按配置转换,保留 response 和原始数据
LuchRequestError.ERR_CANCELED取消或业务主动终止时库取消流程可通过 cancelMode 区分原生与逻辑取消
LuchRequestError.ERR_INTERCEPTORinterceptor 执行或恢复时cause 保留 handler 异常,response 阶段可能带 response

业务分支应比较静态常量,不要比较字符串字面量:

ts
import { LuchRequestError } from 'luch-request'

function handleRequestError(error: LuchRequestError): void {
  switch (error.code) {
    case LuchRequestError.ERR_INVALID_CONFIG:
      reportConfigurationError(error)
      break
    case LuchRequestError.ERR_NETWORK:
      showNetworkMessage(error.raw)
      break
    case LuchRequestError.ERR_BAD_STATUS:
      handleUnexpectedStatus(error.response)
      break
    case LuchRequestError.ERR_BAD_RESPONSE:
      reportInvalidResponse(error.response)
      break
    case LuchRequestError.ERR_CANCELED:
      handleCanceledRequest(error.cancelMode)
      break
    case LuchRequestError.ERR_INTERCEPTOR:
      reportInterceptorError(error.cause)
      break
  }
}

isLuchRequestError()

ts
function isLuchRequestError<TConfig = unknown, TResponse = unknown>(
  value: unknown
): value is LuchRequestError<TConfig, TResponse>

该函数检查公开标记,不依赖可能跨包失效的 instanceof,用于把 catch 中的 unknown 安全收窄为 LuchRequestError

推荐的 catch 写法

ts
try {
  await http.get('/users/1')
} catch (error: unknown) {
  if (!isLuchRequestError(error)) {
    throw error
  }

  console.log(error.code)
  console.log(error.config)
  console.log(error.response)
  console.log(error.task)
  console.log(error.cause)
  console.log(error.raw)
  console.log(error.cancelMode)
}

LuchRequestError.ERR_NETWORKmessage 优先使用平台 fail 错误中的非空 errMsg,其次使用 message 或字符串原因;无法提取时才回退为 Network request failed。因此微信超时通常会直接显示 request:fail timeout。 业务分支仍应判断稳定的 code,不要匹配平台消息文本。

response 能说明请求到达服务端吗

需要按错误来源区分:

场景能得出的结论
库生成的 LuchRequestError.ERR_BAD_STATUS / LuchRequestError.ERR_BAD_RESPONSE 且有 responseuni API 已取得响应
LuchRequestError.ERR_NETWORK只能说明 uni API 报告网络失败,不能证明服务端是否收到
request interceptor 抛错尚未进入对应 uni API
response interceptor 抛错且有 response有响应上下文,但可能由前序 rejected handler 合成

因此,error.response 的体验与 Axios 类似,但不能无条件等价为“服务端一定收到”。 只有明确来自原生响应的状态或转换错误,才能判断平台已经取得响应。服务端是否 真正执行业务,还需要 request ID、服务端日志或幂等协议确认。

原始上下文

  • HTTP 状态错误在 response 中保留完整响应
  • 网络失败在 rawcause 中保留平台错误,并尽量将原始消息提升到 message
  • interceptor 普通异常只保存在 cause
  • 库取消流程通过 cancelMode 区分原生中断与逻辑取消
  • 请求管线逐字段补充缺失的 configtaskresponse

调用方显式提供的字段保持原值。手动设置 cancelMode 只修改错误元数据,不会 触发 Task 取消。

主动抛出统一错误

ts
throw new LuchRequestError(
  '业务主动取消',
  LuchRequestError.ERR_CANCELED
)

通常不需要手动传 config,请求管线会自动补充。只有确实需要覆盖当前上下文的 高级场景才传第三个 options 参数。

toJSON

ts
const summary = error.toJSON()

summary.name
summary.message
summary.stack
summary.code
summary.statusCode
summary.config
summary.cause
summary.raw
summary.cancelMode
summary.isLuchRequestError

toJSON() 不包含原生 Task 或完整 response,也不会克隆、脱敏或处理循环引用。 记录日志前仍需由应用过滤 token、Cookie 等敏感字段。

v4 处于 Alpha 阶段,公共 API 仍可能调整。