ai-c/utils/errorHandler.js
2026-02-02 18:21:32 +08:00

238 lines
5.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 统一错误处理工具
* 提供统一的错误提示和处理机制
*/
/**
* 错误类型映射
*/
const ERROR_TYPES = {
NETWORK: 'network',
AUTH: 'auth',
BUSINESS: 'business',
UNKNOWN: 'unknown'
}
/**
* 错误消息映射
*/
const ERROR_MESSAGES = {
// 网络错误
'request:fail': '网络连接失败,请检查网络设置',
'request:fail timeout': '请求超时,请稍后重试',
'request:fail abort': '请求已取消',
// 认证错误
401: '登录已过期,请重新登录',
403: '没有权限访问',
// 业务错误
400: '请求参数错误',
404: '请求的资源不存在',
500: '服务器错误,请稍后重试',
// 默认错误
default: '操作失败,请稍后重试'
}
/**
* 判断错误类型
* @param {object} error - 错误对象
* @returns {string} 错误类型
*/
function getErrorType(error) {
if (!error) return ERROR_TYPES.UNKNOWN
// 网络错误
if (error.errMsg && error.errMsg.includes('request:fail')) {
return ERROR_TYPES.NETWORK
}
// 认证错误
if (error.code === 401 || error.statusCode === 401) {
return ERROR_TYPES.AUTH
}
// 业务错误
if (error.code || error.statusCode) {
return ERROR_TYPES.BUSINESS
}
return ERROR_TYPES.UNKNOWN
}
/**
* 获取错误消息
* @param {object} error - 错误对象
* @returns {string} 错误消息
*/
function getErrorMessage(error) {
if (!error) return ERROR_MESSAGES.default
// 优先使用后端返回的错误消息
if (error.message) return error.message
if (error.error) return error.error
if (error.msg) return error.msg
// 根据错误码获取消息
const code = error.code || error.statusCode
if (code && ERROR_MESSAGES[code]) {
return ERROR_MESSAGES[code]
}
// 根据错误信息获取消息
if (error.errMsg && ERROR_MESSAGES[error.errMsg]) {
return ERROR_MESSAGES[error.errMsg]
}
return ERROR_MESSAGES.default
}
/**
* 显示错误提示
* @param {object} error - 错误对象
* @param {object} options - 选项
*/
function showError(error, options = {}) {
const {
silent = false, // 是否静默(不显示提示)
duration = 2000, // 提示持续时间
icon = 'none', // 图标类型
mask = false // 是否显示透明蒙层
} = options
if (silent) return
const message = getErrorMessage(error)
const type = getErrorType(error)
// 认证错误不显示toast由auth模块处理
if (type === ERROR_TYPES.AUTH) {
return
}
wx.showToast({
title: message,
icon,
duration,
mask
})
}
/**
* 处理API错误
* @param {object} error - 错误对象
* @param {object} options - 选项
* @returns {object} 处理后的错误对象
*/
function handleApiError(error, options = {}) {
const {
showToast = true, // 是否显示错误提示
logError = true, // 是否记录错误日志
customMessage = null // 自定义错误消息
} = options
// 记录错误日志
if (logError) {
console.error('[Error Handler]', error)
}
// 显示错误提示
if (showToast) {
showError(error, {
silent: false,
duration: 2000
})
}
// 返回标准化的错误对象
return {
type: getErrorType(error),
message: customMessage || getErrorMessage(error),
code: error.code || error.statusCode || -1,
originalError: error
}
}
/**
* 错误重试机制
* @param {function} fn - 要重试的函数
* @param {object} options - 选项
* @returns {Promise}
*/
async function retryOnError(fn, options = {}) {
const {
maxRetries = 3, // 最大重试次数
retryDelay = 1000, // 重试延迟(毫秒)
onRetry = null // 重试回调
} = options
let lastError = null
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
} catch (error) {
lastError = error
// 认证错误不重试
if (getErrorType(error) === ERROR_TYPES.AUTH) {
throw error
}
// 最后一次重试失败,抛出错误
if (i === maxRetries - 1) {
throw error
}
// 执行重试回调
if (onRetry) {
onRetry(i + 1, maxRetries)
}
// 等待后重试
await new Promise(resolve => setTimeout(resolve, retryDelay))
}
}
throw lastError
}
/**
* 检查网络状态
* @returns {Promise<boolean>}
*/
function checkNetworkStatus() {
return new Promise((resolve) => {
wx.getNetworkType({
success: (res) => {
const networkType = res.networkType
if (networkType === 'none') {
wx.showToast({
title: '网络未连接',
icon: 'none',
duration: 2000
})
resolve(false)
} else {
resolve(true)
}
},
fail: () => {
resolve(true) // 获取失败时假设网络正常
}
})
})
}
module.exports = {
ERROR_TYPES,
ERROR_MESSAGES,
getErrorType,
getErrorMessage,
showError,
handleApiError,
retryOnError,
checkNetworkStatus
}