# 存储访问问题 **本文档引用的文件** - [TsStorage.js](file://src/utils/TsStorage.js) - [TsCommon.js](file://src/utils/TsCommon.js) - [TsHttpUtil.js](file://src/https/TsHttpUtil.js) - [TsCrypto.js](file://src/utils/TsCrypto.js) - [TsSM4.js](file://src/utils/TsSM4.js) - [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js) - [index.js](file://index.js) - [package.json](file://package.json) - [README.md](file://README.md) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构概览](#架构概览) 5. [详细组件分析](#详细组件分析) 6. [存储访问故障排除指南](#存储访问故障排除指南) 7. [依赖关系分析](#依赖关系分析) 8. [性能考虑](#性能考虑) 9. [故障排除指南](#故障排除指南) 10. [结论](#结论) ## 简介 本指南专注于存储访问相关的故障排除,涵盖localStorage访问失败、数据读取错误、存储空间不足、数据格式异常等问题的诊断和解决方法。该工具包提供了完整的本地存储解决方案,包括数据序列化、加密存储、错误处理等功能。 ## 项目结构 该项目采用模块化设计,主要包含以下核心模块: ```mermaid graph TB subgraph "主入口" Index[index.js] end subgraph "存储模块" Storage[TsStorage.js] Common[TsCommon.js] end subgraph "网络模块" HttpUtil[TsHttpUtil.js] Crypto[TsCrypto.js] SM4[TsSM4.js] Config[TsGlobalConfig.js] end subgraph "外部依赖" UmiRequest[umi-request] Base64[base64-js] end Index --> Storage Index --> HttpUtil Index --> Crypto Index --> Config Storage --> Common HttpUtil --> Storage HttpUtil --> Crypto Crypto --> SM4 Crypto --> Config HttpUtil --> UmiRequest Crypto --> Base64 ``` **图表来源** - [index.js:1-16](file://index.js#L1-L16) - [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55) - [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171) **章节来源** - [index.js:1-16](file://index.js#L1-L16) - [package.json:1-24](file://package.json#L1-L24) ## 核心组件 ### 存储管理器 (TsStorage) 存储管理器提供了完整的localStorage操作接口,支持数据的保存、读取和用户令牌管理。 **主要功能特性:** - 数据序列化和反序列化 - 用户令牌存储和获取 - 加密开关控制 - 错误处理和默认值机制 ### 通用工具 (TsCommon) 提供了基础的JavaScript工具函数,特别是JSON解析和数据验证功能。 **关键功能:** - 安全的JSON解析 - 空值检测 - 字符串处理工具 ### 网络请求 (TsHttpUtil) 集成了存储功能的HTTP客户端,支持自动数据加密和令牌管理。 **核心特性:** - 自动令牌注入 - 条件数据加密 - 统一错误处理 - 配置化参数处理 ## 架构概览 ```mermaid sequenceDiagram participant Client as 客户端应用 participant Storage as 存储管理器 participant Common as 通用工具 participant Crypto as 加密模块 participant HTTP as HTTP客户端 Client->>Storage : 保存数据 Storage->>Storage : 序列化数据 Storage->>Storage : 写入localStorage Client->>Storage : 读取数据 Storage->>Storage : 从localStorage读取 Storage->>Common : 解析JSON Common-->>Storage : 返回数据 Storage-->>Client : 返回结果 Client->>HTTP : 发送请求 HTTP->>Storage : 获取用户令牌 Storage-->>HTTP : 返回令牌 HTTP->>Crypto : 加密数据(可选) Crypto-->>HTTP : 返回加密结果 HTTP-->>Client : 返回响应 ``` **图表来源** - [TsStorage.js:26-43](file://src/utils/TsStorage.js#L26-L43) - [TsCommon.js:29-44](file://src/utils/TsCommon.js#L29-L44) - [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134) ## 详细组件分析 ### 存储组件深度分析 ```mermaid classDiagram class TsStorage { +save(key, value) void +get(key, def) string +saveUserToken(token) void +getUserToken() string +saveEncryptBody(bool) void +getEncryptBody() boolean } class TsCommon { +parseJSON(value, def) Object +isEmpty(value) boolean +getParamFormUrl(key, host) string +isDevelopment() boolean } class TsHttpUtil { +req(url, options) Promise +get(url, params, options) Promise +post(url, data, options) Promise +form(url, data, options) Promise } class TsCrypto { +encrypt(content) string +decrypt(base64) string } class TsSM4 { +encrypt(plaintext) string +decrypt(ciphertext) string } TsStorage --> TsCommon : 使用 TsHttpUtil --> TsStorage : 依赖 TsHttpUtil --> TsCrypto : 使用 TsCrypto --> TsSM4 : 使用 ``` **图表来源** - [TsStorage.js:26-54](file://src/utils/TsStorage.js#L26-L54) - [TsCommon.js:89-97](file://src/utils/TsCommon.js#L89-L97) - [TsHttpUtil.js:168-170](file://src/https/TsHttpUtil.js#L168-L170) - [TsCrypto.js:5-33](file://src/utils/TsCrypto.js#L5-L33) **章节来源** - [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55) - [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98) - [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171) ## 存储访问故障排除指南 ### 常见存储问题诊断 #### 1. localStorage 访问失败 **症状表现:** - 页面加载时报错,提示localStorage不可用 - 数据无法保存或读取 - 浏览器控制台出现安全错误 **诊断步骤:** 1. 检查浏览器隐私模式设置 2. 验证跨域访问权限 3. 确认浏览器扩展程序影响 4. 检查HTTPS环境要求 **解决方案:** ```javascript // 检查localStorage可用性 function checkLocalStorage() { try { const test = 'test'; localStorage.setItem(test, test); localStorage.removeItem(test); return true; } catch (e) { return false; } } // 降级方案:使用sessionStorage if (!checkLocalStorage()) { console.warn('localStorage不可用,使用sessionStorage作为替代'); } ``` #### 2. 数据读取错误 **症状表现:** - 读取到空值或undefined - JSON解析失败 - 数据类型不匹配 **诊断流程:** ```mermaid flowchart TD Start([开始诊断]) --> CheckKey["检查键名是否存在"] CheckKey --> KeyExists{"键存在?"} KeyExists --> |否| CreateDefault["创建默认值"] KeyExists --> |是| CheckFormat["检查数据格式"] CheckFormat --> FormatOK{"格式正确?"} FormatOK --> |否| ParseError["JSON解析错误"] FormatOK --> |是| DataType["检查数据类型"] DataType --> TypeOK{"类型匹配?"} TypeOK --> |否| ConvertData["转换数据类型"] TypeOK --> |是| Success["诊断完成"] CreateDefault --> Success ParseError --> FixParse["修复JSON格式"] FixParse --> Success ConvertData --> Success ``` **图表来源** - [TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43) - [TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44) **解决方案:** 1. 实施默认值机制 2. 添加数据类型验证 3. 实现错误边界处理 #### 3. 存储空间不足 **症状表现:** - 保存数据时报错 - 随机数据丢失 - 性能明显下降 **诊断方法:** 1. 检查localStorage使用量 2. 分析数据增长趋势 3. 识别大体积数据项 **优化策略:** ```javascript // 存储容量监控 function checkStorageCapacity() { const storage = localStorage; let totalSize = 0; for (let key in storage) { if (storage.hasOwnProperty(key)) { totalSize += storage[key].length; } } return totalSize; } // 清理过期数据 function cleanupExpiredData() { const now = Date.now(); const maxAge = 7 * 24 * 60 * 60 * 1000; // 7天 for (let key in localStorage) { if (localStorage.hasOwnProperty(key)) { try { const item = JSON.parse(localStorage.getItem(key)); if (item.timestamp && (now - item.timestamp) > maxAge) { localStorage.removeItem(key); } } catch (e) { // 忽略格式错误的数据 } } } } ``` #### 4. 数据格式异常 **症状表现:** - JSON解析抛出异常 - 数据损坏或不完整 - 版本升级后数据不兼容 **诊断步骤:** 1. 验证数据完整性 2. 检查版本兼容性 3. 分析数据结构变化 **修复方法:** ```javascript // 安全的数据读取 function safeGet(key, defaultValue = null) { try { const item = localStorage.getItem(key); if (!item) return defaultValue; const parsed = JSON.parse(item); return parsed.data || defaultValue; } catch (error) { console.error(`读取存储项 ${key} 失败:`, error); return defaultValue; } } // 数据格式验证 function validateDataStructure(data) { const requiredFields = ['data']; return requiredFields.every(field => data.hasOwnProperty(field)); } ``` ### 浏览器兼容性问题 #### 1. 不同浏览器的差异 **问题类型:** - Safari隐私模式限制 - IE/Edge兼容性问题 - 移动端存储限制 **解决方案:** ```javascript // 跨浏览器兼容性检查 function isStorageSupported() { const testKey = '__storage_test__'; try { if ('localStorage' in window && window['localStorage'] !== null) { localStorage.setItem(testKey, testKey); localStorage.removeItem(testKey); return true; } return false; } catch (e) { return false; } } // 功能检测而非浏览器检测 function getStorageImplementation() { if (isStorageSupported()) { return localStorage; } else if (typeof sessionStorage !== 'undefined') { return sessionStorage; } else { // 无存储支持,使用内存存储 return createMemoryStorage(); } } ``` #### 2. 存储权限限制 **常见场景:** - 第三方Cookie限制 - HTTPS环境要求 - 用户隐私设置 **处理策略:** ```javascript // 权限检查和降级 function handleStoragePermissions() { const permissions = { localStorage: false, sessionStorage: false, cookies: false }; // 检查localStorage try { localStorage.setItem('permission_test', 'test'); localStorage.removeItem('permission_test'); permissions.localStorage = true; } catch (e) { permissions.localStorage = false; } // 检查cookies try { document.cookie = 'permission_test=test'; permissions.cookies = true; } catch (e) { permissions.cookies = false; } return permissions; } ``` ### 数据序列化失败 #### 1. JSON序列化问题 **常见原因:** - 循环引用 - 函数和undefined - 复杂对象类型 **诊断方法:** ```mermaid flowchart TD Start([序列化开始]) --> CheckCircular["检查循环引用"] CheckCircular --> HasCircular{"存在循环引用?"} HasCircular --> |是| RemoveCircular["移除循环引用"] HasCircular --> |否| CheckTypes["检查数据类型"] CheckTypes --> HasInvalid{"包含无效类型?"} HasInvalid --> |是| FilterInvalid["过滤无效类型"] HasInvalid --> |否| SafeStringify["安全字符串化"] RemoveCircular --> SafeStringify FilterInvalid --> SafeStringify SafeStringify --> Complete["序列化完成"] ``` **图表来源** - [TsStorage.js:31-33](file://src/utils/TsStorage.js#L31-L33) **解决方案:** ```javascript // 安全的JSON序列化 function safeStringify(obj) { const seen = new WeakSet(); return JSON.stringify(obj, (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return "[Circular Reference]"; } seen.add(value); } return value; }); } // 自定义序列化器 function customSerializer(data) { return { data: data, timestamp: Date.now(), version: "1.0" }; } ``` ## 依赖关系分析 ```mermaid graph LR subgraph "核心依赖" A[umi-request] --> B[TsHttpUtil] C[base64-js] --> D[TsCrypto] end subgraph "内部模块" E[TsStorage] --> F[TsCommon] B --> E B --> G[TsCrypto] G --> H[TsSM4] G --> I[TsGlobalConfig] end J[index.js] --> E J --> B J --> G J --> I ``` **图表来源** - [package.json:19-22](file://package.json#L19-L22) - [index.js:1-16](file://index.js#L1-L16) **章节来源** - [package.json:1-24](file://package.json#L1-L24) - [index.js:1-16](file://index.js#L1-L16) ## 性能考虑 ### 存储性能优化 1. **批量操作优化** - 合并多个存储操作 - 使用事务性操作 - 避免频繁的读写 2. **数据压缩** - 对大对象进行压缩 - 实现增量更新 - 使用索引优化查询 3. **缓存策略** - 实现内存缓存 - 设置合理的过期时间 - 支持LRU淘汰算法 ### 数据迁移最佳实践 ```mermaid flowchart TD Start([开始迁移]) --> CheckVersion["检查当前版本"] CheckVersion --> VersionOK{"版本兼容?"} VersionOK --> |是| DirectCopy["直接复制数据"] VersionOK --> |否| TransformData["转换数据格式"] TransformData --> ValidateData["验证数据完整性"] DirectCopy --> ValidateData ValidateData --> MigrationOK{"迁移成功?"} MigrationOK --> |是| UpdateVersion["更新版本号"] MigrationOK --> |否| Rollback["回滚操作"] UpdateVersion --> Complete["迁移完成"] Rollback --> Complete ``` **图表来源** - [TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43) ## 故障排除指南 ### 常见错误信息解读 | 错误类型 | 可能原因 | 解决方案 | |---------|---------|---------| | SecurityError | 跨域访问限制 | 检查域名和协议一致性 | | QuotaExceededError | 存储空间不足 | 清理旧数据或使用压缩 | | InvalidStateError | 存储状态异常 | 重启浏览器或清除缓存 | | TypeError | 数据格式错误 | 实施数据验证和转换 | ### 诊断工具和方法 ```javascript // 存储状态检查 function diagnoseStorage() { const diagnostics = { localStorage: false, sessionStorage: false, quota: 0, items: 0, totalSize: 0 }; // 检查localStorage try { localStorage.setItem('diagnostics', 'test'); localStorage.removeItem('diagnostics'); diagnostics.localStorage = true; } catch (e) { diagnostics.localStorage = false; } // 检查存储配额和使用情况 if (navigator.webkitTemporaryStorage) { navigator.webkitTemporaryStorage.queryUsageAndQuota( (usage, quota) => { diagnostics.quota = quota; diagnostics.used = usage; } ); } // 统计存储项数量和大小 for (let key in localStorage) { if (localStorage.hasOwnProperty(key)) { diagnostics.items++; diagnostics.totalSize += key.length + localStorage[key].length; } } return diagnostics; } // 数据完整性验证 function validateStorageIntegrity() { const errors = []; const keys = Object.keys(localStorage); keys.forEach(key => { try { JSON.parse(localStorage.getItem(key)); } catch (e) { errors.push({ key: key, error: e.message, value: localStorage.getItem(key) }); } }); return errors; } ``` ### 最佳实践建议 1. **错误处理** - 实施全面的try-catch包装 - 提供优雅降级机制 - 记录详细的错误日志 2. **数据保护** - 实施数据备份策略 - 使用版本控制 - 定期数据健康检查 3. **性能监控** - 监控存储使用率 - 跟踪访问模式 - 优化热点数据 **章节来源** - [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55) - [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98) - [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171) ## 结论 存储访问问题的解决需要系统性的方法和完善的监控机制。通过实施本文档提供的诊断流程、故障排除方法和最佳实践,可以有效预防和解决大多数存储相关问题。关键在于建立完善的错误处理机制、实施数据验证和转换、以及持续监控存储状态。 建议在生产环境中: - 实施多层次的错误处理 - 建立存储使用监控 - 定期进行数据完整性检查 - 制定数据迁移和备份策略 这样可以确保应用程序的稳定性和可靠性,为用户提供更好的体验。