upload project
This commit is contained in:
commit
06961cae04
422 changed files with 110626 additions and 0 deletions
695
utils/error-handler.js
Normal file
695
utils/error-handler.js
Normal file
|
|
@ -0,0 +1,695 @@
|
|||
// 全局错误处理管理器 - 微信小程序专用
|
||||
// 统一处理应用中的各种错误,提供错误恢复和降级方案
|
||||
|
||||
const performanceMonitor = require('./performance-monitor.js');
|
||||
|
||||
/**
|
||||
* 全局错误处理管理器
|
||||
* 功能:
|
||||
* 1. 全局错误捕获和处理
|
||||
* 2. 错误分类和分析
|
||||
* 3. 自动重试机制
|
||||
* 4. 降级方案
|
||||
* 5. 错误恢复策略
|
||||
* 6. 用户友好的错误提示
|
||||
*/
|
||||
class ErrorHandler {
|
||||
constructor() {
|
||||
this.isInitialized = false;
|
||||
|
||||
// 错误处理配置
|
||||
this.config = {
|
||||
// 错误处理开关
|
||||
enabled: true,
|
||||
|
||||
// 自动重试配置
|
||||
retry: {
|
||||
enabled: true,
|
||||
maxAttempts: 3,
|
||||
baseDelay: 1000, // 基础延迟 (ms)
|
||||
maxDelay: 10000, // 最大延迟 (ms)
|
||||
backoffFactor: 2 // 退避因子
|
||||
},
|
||||
|
||||
// 降级配置
|
||||
fallback: {
|
||||
enabled: true,
|
||||
cacheTimeout: 300000, // 缓存超时 (5分钟)
|
||||
offlineMode: true // 离线模式
|
||||
},
|
||||
|
||||
// 用户提示配置
|
||||
userNotification: {
|
||||
enabled: true,
|
||||
showDetails: false, // 是否显示错误详情
|
||||
autoHide: true, // 自动隐藏
|
||||
hideDelay: 3000 // 隐藏延迟 (ms)
|
||||
}
|
||||
};
|
||||
|
||||
// 错误类型定义
|
||||
this.errorTypes = {
|
||||
NETWORK_ERROR: 'network_error',
|
||||
API_ERROR: 'api_error',
|
||||
PARSE_ERROR: 'parse_error',
|
||||
STORAGE_ERROR: 'storage_error',
|
||||
PERMISSION_ERROR: 'permission_error',
|
||||
VALIDATION_ERROR: 'validation_error',
|
||||
UNKNOWN_ERROR: 'unknown_error'
|
||||
};
|
||||
|
||||
// 错误统计
|
||||
this.errorStats = {
|
||||
totalErrors: 0,
|
||||
errorsByType: new Map(),
|
||||
errorsByPage: new Map(),
|
||||
recentErrors: []
|
||||
};
|
||||
|
||||
// 重试队列
|
||||
this.retryQueue = new Map();
|
||||
|
||||
// 降级缓存
|
||||
this.fallbackCache = new Map();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
// 初始化错误处理器
|
||||
init() {
|
||||
if (this.isInitialized || !this.config.enabled) return;
|
||||
|
||||
try {
|
||||
// 设置全局错误监听
|
||||
this.setupGlobalErrorHandlers();
|
||||
|
||||
// 设置网络错误监听
|
||||
this.setupNetworkErrorHandlers();
|
||||
|
||||
// 设置Promise错误监听
|
||||
this.setupPromiseErrorHandlers();
|
||||
|
||||
this.isInitialized = true;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 全局错误处理器初始化失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 🚨 ===== 错误捕获和处理 =====
|
||||
|
||||
// 处理错误
|
||||
handleError(error, context = {}) {
|
||||
if (!this.config.enabled) return;
|
||||
|
||||
try {
|
||||
// 错误分类
|
||||
const errorType = this.classifyError(error);
|
||||
|
||||
// 创建错误信息
|
||||
const errorInfo = this.createErrorInfo(error, errorType, context);
|
||||
|
||||
// 更新错误统计
|
||||
this.updateErrorStats(errorInfo);
|
||||
|
||||
// 记录错误到性能监控
|
||||
performanceMonitor.recordError(error, context);
|
||||
|
||||
// 处理特定类型的错误
|
||||
this.handleSpecificError(errorInfo);
|
||||
|
||||
// 显示用户提示
|
||||
this.showUserNotification(errorInfo);
|
||||
|
||||
console.error('🚨 错误处理:', errorInfo);
|
||||
|
||||
return errorInfo;
|
||||
|
||||
} catch (handlerError) {
|
||||
console.error('❌ 错误处理器本身出错:', handlerError);
|
||||
}
|
||||
}
|
||||
|
||||
// 错误分类
|
||||
classifyError(error) {
|
||||
if (!error) return this.errorTypes.UNKNOWN_ERROR;
|
||||
|
||||
const message = error.message || error.toString();
|
||||
const stack = error.stack || '';
|
||||
|
||||
// 网络错误
|
||||
if (message.includes('network') || message.includes('timeout') ||
|
||||
message.includes('连接') || error.code === 'NETWORK_ERROR') {
|
||||
return this.errorTypes.NETWORK_ERROR;
|
||||
}
|
||||
|
||||
// API错误
|
||||
if (message.includes('API') || message.includes('request') ||
|
||||
message.includes('response') || error.statusCode) {
|
||||
return this.errorTypes.API_ERROR;
|
||||
}
|
||||
|
||||
// 解析错误
|
||||
if (message.includes('JSON') || message.includes('parse') ||
|
||||
message.includes('Unexpected token')) {
|
||||
return this.errorTypes.PARSE_ERROR;
|
||||
}
|
||||
|
||||
// 存储错误
|
||||
if (message.includes('storage') || message.includes('setStorage') ||
|
||||
message.includes('getStorage')) {
|
||||
return this.errorTypes.STORAGE_ERROR;
|
||||
}
|
||||
|
||||
// 权限错误
|
||||
if (message.includes('permission') || message.includes('unauthorized') ||
|
||||
message.includes('权限') || error.code === 'PERMISSION_DENIED') {
|
||||
return this.errorTypes.PERMISSION_ERROR;
|
||||
}
|
||||
|
||||
// 验证错误
|
||||
if (message.includes('validation') || message.includes('invalid') ||
|
||||
message.includes('验证')) {
|
||||
return this.errorTypes.VALIDATION_ERROR;
|
||||
}
|
||||
|
||||
return this.errorTypes.UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// 创建错误信息
|
||||
createErrorInfo(error, errorType, context) {
|
||||
return {
|
||||
id: this.generateErrorId(),
|
||||
timestamp: Date.now(),
|
||||
type: errorType,
|
||||
message: error.message || error.toString(),
|
||||
stack: error.stack || null,
|
||||
code: error.code || null,
|
||||
statusCode: error.statusCode || null,
|
||||
context: context,
|
||||
pagePath: this.getCurrentPagePath(),
|
||||
userAgent: this.getUserAgent(),
|
||||
canRetry: this.canRetry(errorType),
|
||||
canFallback: this.canFallback(errorType),
|
||||
severity: this.getErrorSeverity(errorType)
|
||||
};
|
||||
}
|
||||
|
||||
// 🔄 ===== 自动重试机制 =====
|
||||
|
||||
// 自动重试
|
||||
async autoRetry(operation, context = {}) {
|
||||
if (!this.config.retry.enabled) {
|
||||
return await operation();
|
||||
}
|
||||
|
||||
const retryId = this.generateRetryId();
|
||||
let lastError = null;
|
||||
|
||||
for (let attempt = 1; attempt <= this.config.retry.maxAttempts; attempt++) {
|
||||
try {
|
||||
// 记录重试尝试
|
||||
if (attempt > 1) {
|
||||
|
||||
}
|
||||
|
||||
const result = await operation();
|
||||
|
||||
// 成功,清除重试记录
|
||||
this.retryQueue.delete(retryId);
|
||||
|
||||
return result;
|
||||
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
|
||||
// 检查是否可以重试
|
||||
if (!this.canRetry(this.classifyError(error)) || attempt >= this.config.retry.maxAttempts) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 计算延迟时间
|
||||
const delay = this.calculateRetryDelay(attempt);
|
||||
|
||||
// 记录重试信息
|
||||
this.retryQueue.set(retryId, {
|
||||
attempt: attempt,
|
||||
nextRetry: Date.now() + delay,
|
||||
context: context,
|
||||
error: error
|
||||
});
|
||||
|
||||
// 等待重试
|
||||
await this.sleep(delay);
|
||||
}
|
||||
}
|
||||
|
||||
// 所有重试都失败了
|
||||
this.retryQueue.delete(retryId);
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
// 计算重试延迟
|
||||
calculateRetryDelay(attempt) {
|
||||
const delay = this.config.retry.baseDelay * Math.pow(this.config.retry.backoffFactor, attempt - 1);
|
||||
return Math.min(delay, this.config.retry.maxDelay);
|
||||
}
|
||||
|
||||
// 检查是否可以重试
|
||||
canRetry(errorType) {
|
||||
const retryableErrors = [
|
||||
this.errorTypes.NETWORK_ERROR,
|
||||
this.errorTypes.API_ERROR
|
||||
];
|
||||
|
||||
return retryableErrors.includes(errorType);
|
||||
}
|
||||
|
||||
// 🔄 ===== 降级方案 =====
|
||||
|
||||
// 降级处理
|
||||
async fallbackHandler(operation, fallbackKey, fallbackData = null) {
|
||||
if (!this.config.fallback.enabled) {
|
||||
return await operation();
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await operation();
|
||||
|
||||
// 成功时更新缓存
|
||||
this.updateFallbackCache(fallbackKey, result);
|
||||
|
||||
return result;
|
||||
|
||||
} catch (error) {
|
||||
console.warn('🔄 操作失败,尝试降级方案:', error.message);
|
||||
|
||||
// 尝试从缓存获取数据
|
||||
const cachedData = this.getFallbackCache(fallbackKey);
|
||||
if (cachedData) {
|
||||
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
// 使用提供的降级数据
|
||||
if (fallbackData !== null) {
|
||||
|
||||
return fallbackData;
|
||||
}
|
||||
|
||||
// 没有降级方案,重新抛出错误
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新降级缓存
|
||||
updateFallbackCache(key, data) {
|
||||
this.fallbackCache.set(key, {
|
||||
data: data,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
// 获取降级缓存
|
||||
getFallbackCache(key) {
|
||||
const cached = this.fallbackCache.get(key);
|
||||
|
||||
if (!cached) return null;
|
||||
|
||||
// 检查缓存是否过期
|
||||
if (Date.now() - cached.timestamp > this.config.fallback.cacheTimeout) {
|
||||
this.fallbackCache.delete(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return cached.data;
|
||||
}
|
||||
|
||||
// 检查是否可以降级
|
||||
canFallback(errorType) {
|
||||
const fallbackableErrors = [
|
||||
this.errorTypes.NETWORK_ERROR,
|
||||
this.errorTypes.API_ERROR
|
||||
];
|
||||
|
||||
return fallbackableErrors.includes(errorType);
|
||||
}
|
||||
|
||||
// 📱 ===== 用户提示 =====
|
||||
|
||||
// 显示用户提示
|
||||
showUserNotification(errorInfo) {
|
||||
if (!this.config.userNotification.enabled) return;
|
||||
|
||||
// 只对已登录用户显示弹窗
|
||||
const app = getApp();
|
||||
const isLoggedIn = app?.globalData?.isLoggedIn || false;
|
||||
if (!isLoggedIn) return;
|
||||
|
||||
const userMessage = this.getUserFriendlyMessage(errorInfo);
|
||||
|
||||
// 根据错误严重程度选择提示方式
|
||||
switch (errorInfo.severity) {
|
||||
case 'low':
|
||||
// 低严重程度,不显示提示或显示简单提示
|
||||
break;
|
||||
|
||||
case 'medium':
|
||||
wx.showToast({
|
||||
title: userMessage,
|
||||
icon: 'none',
|
||||
duration: this.config.userNotification.hideDelay
|
||||
});
|
||||
break;
|
||||
|
||||
case 'high':
|
||||
wx.showModal({
|
||||
title: '操作失败',
|
||||
content: userMessage,
|
||||
showCancel: false,
|
||||
confirmText: '确定'
|
||||
});
|
||||
break;
|
||||
|
||||
case 'critical':
|
||||
wx.showModal({
|
||||
title: '严重错误',
|
||||
content: userMessage + '\n\n建议重启应用或联系客服。',
|
||||
showCancel: true,
|
||||
cancelText: '稍后处理',
|
||||
confirmText: '重启应用',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.reLaunch({
|
||||
url: '/pages/splash/splash'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户友好的错误消息
|
||||
getUserFriendlyMessage(errorInfo) {
|
||||
const messageMap = {
|
||||
[this.errorTypes.NETWORK_ERROR]: '网络连接异常,请检查网络设置',
|
||||
[this.errorTypes.API_ERROR]: '服务暂时不可用,请稍后重试',
|
||||
[this.errorTypes.PARSE_ERROR]: '数据格式错误,请稍后重试',
|
||||
[this.errorTypes.STORAGE_ERROR]: '存储空间不足或存储异常',
|
||||
[this.errorTypes.PERMISSION_ERROR]: '权限不足,请检查相关权限设置',
|
||||
[this.errorTypes.VALIDATION_ERROR]: '输入信息有误,请检查后重试',
|
||||
[this.errorTypes.UNKNOWN_ERROR]: '操作失败,请稍后重试'
|
||||
};
|
||||
|
||||
let message = messageMap[errorInfo.type] || messageMap[this.errorTypes.UNKNOWN_ERROR];
|
||||
|
||||
// 如果配置显示详情,添加错误详情
|
||||
if (this.config.userNotification.showDetails && errorInfo.message) {
|
||||
message += `\n\n详情: ${errorInfo.message}`;
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
// 获取错误严重程度
|
||||
getErrorSeverity(errorType) {
|
||||
const severityMap = {
|
||||
[this.errorTypes.NETWORK_ERROR]: 'medium',
|
||||
[this.errorTypes.API_ERROR]: 'medium',
|
||||
[this.errorTypes.PARSE_ERROR]: 'high',
|
||||
[this.errorTypes.STORAGE_ERROR]: 'high',
|
||||
[this.errorTypes.PERMISSION_ERROR]: 'medium',
|
||||
[this.errorTypes.VALIDATION_ERROR]: 'low',
|
||||
[this.errorTypes.UNKNOWN_ERROR]: 'high'
|
||||
};
|
||||
|
||||
return severityMap[errorType] || 'medium';
|
||||
}
|
||||
|
||||
// 🔧 ===== 特定错误处理 =====
|
||||
|
||||
// 处理特定类型的错误
|
||||
handleSpecificError(errorInfo) {
|
||||
switch (errorInfo.type) {
|
||||
case this.errorTypes.NETWORK_ERROR:
|
||||
this.handleNetworkError(errorInfo);
|
||||
break;
|
||||
|
||||
case this.errorTypes.API_ERROR:
|
||||
this.handleApiError(errorInfo);
|
||||
break;
|
||||
|
||||
case this.errorTypes.STORAGE_ERROR:
|
||||
this.handleStorageError(errorInfo);
|
||||
break;
|
||||
|
||||
case this.errorTypes.PERMISSION_ERROR:
|
||||
this.handlePermissionError(errorInfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.handleGenericError(errorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理网络错误
|
||||
handleNetworkError(errorInfo) {
|
||||
|
||||
// 检查网络状态
|
||||
wx.getNetworkType({
|
||||
success: (res) => {
|
||||
if (res.networkType === 'none') {
|
||||
// 无网络连接
|
||||
this.handleOfflineMode();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 处理API错误
|
||||
handleApiError(errorInfo) {
|
||||
|
||||
// 根据状态码进行特殊处理
|
||||
if (errorInfo.statusCode === 401) {
|
||||
// 未授权,可能需要重新登录
|
||||
this.handleUnauthorizedError();
|
||||
} else if (errorInfo.statusCode >= 500) {
|
||||
// 服务器错误,可以尝试重试
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 处理存储错误
|
||||
handleStorageError(errorInfo) {
|
||||
|
||||
// 尝试清理存储空间
|
||||
this.cleanupStorage();
|
||||
}
|
||||
|
||||
// 处理权限错误
|
||||
handlePermissionError(errorInfo) {
|
||||
|
||||
// 可以引导用户去设置页面
|
||||
}
|
||||
|
||||
// 处理通用错误
|
||||
handleGenericError(errorInfo) {
|
||||
|
||||
}
|
||||
|
||||
// 处理离线模式
|
||||
handleOfflineMode() {
|
||||
if (!this.config.fallback.offlineMode) return;
|
||||
|
||||
// 可以设置全局离线状态
|
||||
// app.globalData.isOffline = true;
|
||||
}
|
||||
|
||||
// 处理未授权错误
|
||||
handleUnauthorizedError() {
|
||||
|
||||
// 清除本地token
|
||||
wx.removeStorageSync('token');
|
||||
|
||||
// 跳转到登录页面
|
||||
wx.reLaunch({
|
||||
url: '/pages/login/login'
|
||||
});
|
||||
}
|
||||
|
||||
// 清理存储空间
|
||||
cleanupStorage() {
|
||||
try {
|
||||
// 获取存储信息
|
||||
const storageInfo = wx.getStorageInfoSync();
|
||||
|
||||
if (storageInfo.currentSize > storageInfo.limitSize * 0.8) {
|
||||
// 存储空间使用超过80%,进行清理
|
||||
|
||||
// 清理缓存数据
|
||||
const keysToClean = ['cache_', 'temp_', 'old_'];
|
||||
|
||||
storageInfo.keys.forEach(key => {
|
||||
if (keysToClean.some(prefix => key.startsWith(prefix))) {
|
||||
wx.removeStorageSync(key);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 清理存储空间失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 📊 ===== 错误统计 =====
|
||||
|
||||
// 更新错误统计
|
||||
updateErrorStats(errorInfo) {
|
||||
this.errorStats.totalErrors++;
|
||||
|
||||
// 按类型统计
|
||||
const typeCount = this.errorStats.errorsByType.get(errorInfo.type) || 0;
|
||||
this.errorStats.errorsByType.set(errorInfo.type, typeCount + 1);
|
||||
|
||||
// 按页面统计
|
||||
const pageCount = this.errorStats.errorsByPage.get(errorInfo.pagePath) || 0;
|
||||
this.errorStats.errorsByPage.set(errorInfo.pagePath, pageCount + 1);
|
||||
|
||||
// 记录最近错误
|
||||
this.errorStats.recentErrors.push(errorInfo);
|
||||
|
||||
// 保持最近50条错误记录
|
||||
if (this.errorStats.recentErrors.length > 50) {
|
||||
this.errorStats.recentErrors.shift();
|
||||
}
|
||||
}
|
||||
|
||||
// 获取错误统计
|
||||
getErrorStats() {
|
||||
return {
|
||||
totalErrors: this.errorStats.totalErrors,
|
||||
errorsByType: Object.fromEntries(this.errorStats.errorsByType),
|
||||
errorsByPage: Object.fromEntries(this.errorStats.errorsByPage),
|
||||
recentErrors: this.errorStats.recentErrors.slice(-10), // 最近10条
|
||||
errorRate: this.calculateErrorRate()
|
||||
};
|
||||
}
|
||||
|
||||
// 计算错误率
|
||||
calculateErrorRate() {
|
||||
const sessionDuration = Date.now() - (performanceMonitor.monitoringState?.startTime || Date.now());
|
||||
const hours = sessionDuration / (1000 * 60 * 60);
|
||||
|
||||
return hours > 0 ? this.errorStats.totalErrors / hours : 0;
|
||||
}
|
||||
|
||||
// 🔧 ===== 工具方法 =====
|
||||
|
||||
// 设置全局错误监听
|
||||
setupGlobalErrorHandlers() {
|
||||
// 微信小程序的错误监听
|
||||
wx.onError((error) => {
|
||||
this.handleError(new Error(error), { source: 'global' });
|
||||
});
|
||||
|
||||
// 监听未处理的Promise拒绝
|
||||
wx.onUnhandledRejection((res) => {
|
||||
this.handleError(res.reason, { source: 'unhandled_promise' });
|
||||
});
|
||||
}
|
||||
|
||||
// 设置网络错误监听
|
||||
setupNetworkErrorHandlers() {
|
||||
// 监听网络状态变化
|
||||
wx.onNetworkStatusChange((res) => {
|
||||
if (!res.isConnected) {
|
||||
this.handleError(new Error('Network disconnected'), {
|
||||
source: 'network_change',
|
||||
networkType: res.networkType
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 设置Promise错误监听
|
||||
setupPromiseErrorHandlers() {
|
||||
// 这个在微信小程序中通过wx.onUnhandledRejection已经处理
|
||||
}
|
||||
|
||||
// 生成错误ID
|
||||
generateErrorId() {
|
||||
return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
}
|
||||
|
||||
// 生成重试ID
|
||||
generateRetryId() {
|
||||
return `retry_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
}
|
||||
|
||||
// 获取当前页面路径
|
||||
getCurrentPagePath() {
|
||||
try {
|
||||
const pages = getCurrentPages();
|
||||
if (!pages || pages.length === 0) {
|
||||
console.warn('没有找到当前页面信息');
|
||||
return 'unknown';
|
||||
}
|
||||
const currentPage = pages[pages.length - 1];
|
||||
if (!currentPage || !currentPage.route) {
|
||||
console.warn('当前页面或路由信息不存在');
|
||||
return 'unknown';
|
||||
}
|
||||
return currentPage.route;
|
||||
} catch (error) {
|
||||
console.error('获取当前页面路径失败:', error);
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户代理
|
||||
getUserAgent() {
|
||||
try {
|
||||
// 使用新的API替代已弃用的wx.getSystemInfoSync
|
||||
const deviceInfo = wx.getDeviceInfo();
|
||||
const appBaseInfo = wx.getAppBaseInfo();
|
||||
return `${deviceInfo.platform} ${deviceInfo.system} WeChat/${appBaseInfo.version}`;
|
||||
} catch (error) {
|
||||
// 兜底方案
|
||||
try {
|
||||
const systemInfo = wx.getSystemInfoSync();
|
||||
return `${systemInfo.platform} ${systemInfo.system} WeChat/${systemInfo.version}`;
|
||||
} catch (fallbackError) {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 睡眠函数
|
||||
sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
// 销毁错误处理器
|
||||
destroy() {
|
||||
this.errorStats = {
|
||||
totalErrors: 0,
|
||||
errorsByType: new Map(),
|
||||
errorsByPage: new Map(),
|
||||
recentErrors: []
|
||||
};
|
||||
|
||||
this.retryQueue.clear();
|
||||
this.fallbackCache.clear();
|
||||
|
||||
this.isInitialized = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局实例
|
||||
const errorHandler = new ErrorHandler();
|
||||
|
||||
module.exports = errorHandler;
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue