OpenHarmonyToolkitsPlaza:鸿蒙工具错误处理最佳实践
OpenHarmonyToolkitsPlaza:鸿蒙工具错误处理最佳实践
【免费下载链接】鸿蒙开发工具大赶集 本仓将收集和展示鸿蒙开发工具,欢迎大家踊跃投稿。通过pr附上您的工具介绍和使用指南,并加上工具对应的链接,通过的工具将会成功上架到我们社区。 项目地址: https://gitcode.com/OpenHarmonyToolkitsPlaza/harmony-tools
引言
在鸿蒙(HarmonyOS)应用开发过程中,错误处理是确保应用稳定性和用户体验的关键环节。OpenHarmonyToolkitsPlaza 作为鸿蒙开发工具的集合平台,提供了丰富的错误处理机制和工具库。本文将深入探讨鸿蒙开发中的错误处理策略,结合平台提供的工具库,为开发者提供一套完整的错误处理解决方案。
错误处理的重要性
为什么需要专业的错误处理?
鸿蒙工具库中的错误处理机制
1. 统一的错误返回模型
在 eftool
库中,提供了 OutDTO
类作为统一的错误返回模型:
// OutDTO 错误返回模型示例class OutDTO { private success: boolean; // 成功失败标识 private msg: string; // 返回提示信息 private dataRow?: T; // 返回单行数据 private dataTable?: Array; // 返回数据集合 // 成功返回方法 static OK(message: string): OutDTO { return new OutDTO(true, message); } static OKByDataRow(message: string, data: T): OutDTO { const dto = new OutDTO(true, message); dto.setDataRow(data); return dto; } // 错误返回方法 static Error(message: string): OutDTO { return new OutDTO(false, message); } static ErrorByDataRow(message: string, data: T): OutDTO { const dto = new OutDTO(false, message); dto.setDataRow(data); return dto; }}
2. 实际应用示例
// 身份证验证错误处理示例import { IdCardUtil, OutDTO } from \'@yunkss/eftool\';async function validateIdCard(idCard: string): Promise<OutDTO> { try { const result = IdCardUtil.isValidCard18(idCard); if (!result.getSuccess()) { return OutDTO.Error(`身份证验证失败: ${result.getMsg()}`); } // 获取省份信息 const provinceInfo = IdCardUtil.getProvinceCodeByIdCard(idCard); if (!provinceInfo.getSuccess()) { return OutDTO.ErrorByDataRow( \"获取省份信息失败\", provinceInfo.getMsg() ); } return OutDTO.OKByDataRow( \"身份证验证成功\", provinceInfo.getDataRow() ); } catch (error) { // 记录详细错误日志 Logger.error(\"身份证验证异常\", error.message); return OutDTO.Error(\"系统异常,请稍后重试\"); }}// 使用示例const validationResult = await validateIdCard(\"781111199407190143\");if (validationResult.getSuccess()) { console.info(`验证成功: ${validationResult.getDataRow()}`);} else { console.error(`验证失败: ${validationResult.getMsg()}`); // 显示用户友好的错误提示 showErrorToast(validationResult.getMsg());}
日志记录与监控
多级别日志管理
OpenHarmonyToolkitsPlaza 提供了多个日志工具,包括 qlog
和 log4a
:
日志工具配置示例
// log4a 配置示例import { LogManager, Logger, TraceEntry, TraceExit } from \'@pie/log4a\';class UserService { private logger: Logger = LogManager.getLogger(this); @TraceEntry @TraceExit async getUserInfo(userId: string): Promise<OutDTO> { try { this.logger.info(`开始获取用户信息`, `用户ID: ${userId}`); const userData = await api.getUser(userId); if (!userData) { this.logger.warn(`用户不存在`, `用户ID: ${userId}`); return OutDTO.Error(\"用户不存在\"); } this.logger.debug(`用户数据获取成功`, JSON.stringify(userData)); return OutDTO.OKByDataRow(\"获取成功\", userData); } catch (error) { this.logger.error(`获取用户信息异常`, `用户ID: ${userId}, 错误: ${error.message}`); return OutDTO.Error(\"系统繁忙,请稍后重试\"); } }}// qlog 初始化配置class LogDep implements LogDependency { isDebug(): boolean { return true; // 开发环境开启debug } getFileLogLevel(): number { return LogLevel.LEVEL_ERROR; // 生产环境只记录错误日志 }}LogSdk.init(this.context.getApplicationContext(), new LogDep());
错误分类处理策略
1. 网络错误处理
class NetworkErrorHandler { private static readonly MAX_RETRY = 3; private static readonly RETRY_DELAY = 1000; static async withRetry( operation: () => Promise<OutDTO>, operationName: string ): Promise<OutDTO> { let attempt = 0; while (attempt < this.MAX_RETRY) { try { const result = await operation(); if (result.getSuccess()) { return result; } // 如果是网络错误,进行重试 if (this.isNetworkError(result.getMsg())) { attempt++; if (attempt = this.MAX_RETRY) { return OutDTO.Error(`${operationName} 失败: ${error.message}`); } await this.delay(this.RETRY_DELAY * attempt); } } return OutDTO.Error(`${operationName} 重试多次后失败`); } private static isNetworkError(message: string): boolean { const networkErrors = [ \'network\', \'timeout\', \'socket\', \'连接\', \'请求失败\' ]; return networkErrors.some(keyword => message.toLowerCase().includes(keyword.toLowerCase()) ); } private static delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); }}// 使用示例const result = await NetworkErrorHandler.withRetry( () => userService.getUserInfo(\"123\"), \"获取用户信息\");
2. 数据验证错误处理
class DataValidator { static validateUserInput(input: any): OutDTO { const errors: string[] = []; // 必填字段验证 if (!input.username || input.username.trim().length === 0) { errors.push(\"用户名不能为空\"); } if (!input.email || !this.isValidEmail(input.email)) { errors.push(\"邮箱格式不正确\"); } if (input.password && input.password.length 0) { return OutDTO.Error(errors.join(\"; \")); } return OutDTO.OK(\"验证通过\"); } private static isValidEmail(email: string): boolean { const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/; return emailRegex.test(email); }}
用户体验优化
错误提示的最佳实践
class ErrorPresenter { static showError(errorResult: OutDTO): void { const errorMessage = this.getUserFriendlyMessage(errorResult.getMsg()); // 根据错误类型选择不同的提示方式 if (this.isCriticalError(errorResult.getMsg())) { DialogUtil.showDialog({ title: \'系统提示\', msg: errorMessage, okText: \'确定\', okCallBack: () => this.handleCriticalError() }); } else { ToastUtil.showToast(errorMessage, { duration: 3000, bottom: \'50vp\' }); } } private static getUserFriendlyMessage(technicalMessage: string): string { const messageMap: { [key: string]: string } = { \'network error\': \'网络连接失败,请检查网络设置\', \'timeout\': \'请求超时,请稍后重试\', \'invalid data\': \'数据格式错误\', \'user not found\': \'用户不存在\', \'permission denied\': \'权限不足,无法执行此操作\' }; return messageMap[technicalMessage.toLowerCase()] || \'系统繁忙,请稍后重试\'; } private static isCriticalError(message: string): boolean { const criticalErrors = [ \'permission denied\', \'authentication failed\', \'system error\' ]; return criticalErrors.some(error => message.toLowerCase().includes(error.toLowerCase()) ); } private static handleCriticalError(): void { // 处理严重错误,如重新登录等 }}
监控与上报体系
错误监控架构
错误上报实现
class ErrorReporter { private static readonly REPORT_URL = \'/api/errors/report\'; private static readonly BATCH_SIZE = 10; private static pendingErrors: ErrorData[] = []; static reportError(error: ErrorData): void { this.pendingErrors.push(error); if (this.pendingErrors.length >= this.BATCH_SIZE) { this.flushErrors(); } } static flushErrors(): void { if (this.pendingErrors.length === 0) return; const errorsToSend = [...this.pendingErrors]; this.pendingErrors = []; // 异步上报,不阻塞主线程 setTimeout(async () => { try { await fetch(this.REPORT_URL, { method: \'POST\', headers: { \'Content-Type\': \'application/json\' }, body: JSON.stringify({ appVersion: AppInfo.version, deviceInfo: DeviceInfo.model, errors: errorsToSend }) }); } catch (reportError) { // 上报失败,重新加入待发送队列 this.pendingErrors.push(...errorsToSend); } }, 0); } // 定时刷新 static startAutoFlush(interval: number = 30000): void { setInterval(() => this.flushErrors(), interval); }}interface ErrorData { timestamp: number; level: \'error\' | \'warning\' | \'info\'; message: string; stackTrace?: string; context: any;}
最佳实践总结
错误处理 checklist
性能考虑
class PerformanceAwareErrorHandler { // 避免在频繁调用的方法中使用昂贵的错误处理 static lightweightError(message: string): void { // 简单的错误处理,不影响性能 if (__DEV__) { console.warn(message); } } // 重要的错误才进行详细处理 static detailedError(error: Error, context: any): void { if (this.shouldHandleInDetail(error)) { ErrorReporter.reportError({ timestamp: Date.now(), level: \'error\', message: error.message, stackTrace: error.stack, context: context }); } } private static shouldHandleInDetail(error: Error): boolean { // 根据错误类型决定是否详细处理 const ignoreErrors = [ \'NetworkError\', \'TimeoutError\' ]; return !ignoreErrors.some(type => error.name.includes(type)); }}
结语
OpenHarmonyToolkitsPlaza 为鸿蒙开发者提供了一套完整的错误处理解决方案。通过统一的错误模型、多级别日志系统、智能的错误分类和处理策略,开发者可以构建出更加稳定、可靠的鸿蒙应用。记住,良好的错误处理不仅是技术问题,更是用户体验的重要组成部分。
在实际开发中,建议根据具体业务场景选择合适的错误处理策略,并建立完善的错误监控和反馈机制,持续优化应用的稳定性和用户体验。
【免费下载链接】鸿蒙开发工具大赶集 本仓将收集和展示鸿蒙开发工具,欢迎大家踊跃投稿。通过pr附上您的工具介绍和使用指南,并加上工具对应的链接,通过的工具将会成功上架到我们社区。 项目地址: https://gitcode.com/OpenHarmonyToolkitsPlaza/harmony-tools
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考