React Native文件操作:本地存储与云存储集成方案

React Native文件操作:本地存储与云存储集成方案

【免费下载链接】react-native 一个用于构建原生移动应用程序的 JavaScript 库,可以用于构建 iOS 和 Android 应用程序,支持多种原生移动平台,如 iOS,Android,React Native 等。 【免费下载链接】react-native 项目地址: https://gitcode.com/GitHub_Trending/re/react-native

引言:移动应用数据存储的困境与解决方案

在React Native开发中,开发者常常面临数据存储的三重挑战:存储容量限制跨设备同步离线访问支持。传统解决方案往往将本地存储与云存储割裂处理,导致代码冗余和数据一致性问题。本文将系统介绍React Native生态中完整的存储解决方案,从基础的本地存储API到企业级云同步架构,帮助开发者构建可靠、高效的数据存储系统。

一、React Native存储生态系统概览

React Native提供了多层次的存储解决方案,从简单的键值对存储到复杂的文件系统操作,每种方案都有其适用场景:

mermaid

存储方案决策指南

存储需求推荐方案数据容量性能特点安全性
用户偏好设置AsyncStorage<1MB毫秒级读取
认证令牌react-native-keychain<1KB快速访问
离线文档react-native-fs无限制取决于文件大小
结构化数据Realm无限制复杂查询高效
跨设备同步Firebase Cloud Firestore无限制实时同步

二、本地存储实现方案

2.1 AsyncStorage迁移与使用指南

虽然AsyncStorage已从React Native核心库迁移至社区维护(@react-native-async-storage/async-storage),但它仍是轻量级键值存储的首选方案:

安装与配置

# 使用npm安装
npm install @react-native-async-storage/async-storage

# 使用yarn安装
yarn add @react-native-async-storage/async-storage

# 对于iOS项目
cd ios && pod install && cd ..

基础操作封装

// storage/AsyncStorageService.js
import AsyncStorage from '@react-native-async-storage/async-storage';

export const StorageService = {
  /**
   * 存储数据
   * @param {string} key - 存储键名
   * @param {any} value - 存储值(将被JSON序列化)
   * @returns {Promise<void>}
   */
  setItem: async (key, value) => {
    try {
      const jsonValue = JSON.stringify(value);
      await AsyncStorage.setItem(key, jsonValue);
    } catch (e) {
      console.error('AsyncStorage setItem error:', e);
      throw new Error(`存储失败: ${e.message}`);
    }
  },

  /**
   * 获取数据
   * @param {string} key - 存储键名
   * @returns {Promise<any>} - 返回解析后的值或null
   */
  getItem: async (key) => {
    try {
      const jsonValue = await AsyncStorage.getItem(key);
      return jsonValue != null ? JSON.parse(jsonValue) : null;
    } catch (e) {
      console.error('AsyncStorage getItem error:', e);
      throw new Error(`获取失败: ${e.message}`);
    }
  },

  /**
   * 删除数据
   * @param {string} key - 存储键名
   * @returns {Promise<void>}
   */
  removeItem: async (key) => {
    try {
      await AsyncStorage.removeItem(key);
    } catch (e) {
      console.error('AsyncStorage removeItem error:', e);
      throw new Error(`删除失败: ${e.message}`);
    }
  },

  /**
   * 清空所有存储数据
   * @returns {Promise<void>}
   */
  clear: async () => {
    try {
      await AsyncStorage.clear();
    } catch (e) {
      console.error('AsyncStorage clear error:', e);
      throw new Error(`清空失败: ${e.message}`);
    }
  },

  /**
   * 获取所有键名
   * @returns {Promise<string[]>} - 键名数组
   */
  getAllKeys: async () => {
    try {
      return await AsyncStorage.getAllKeys();
    } catch (e) {
      console.error('AsyncStorage getAllKeys error:', e);
      throw new Error(`获取键名失败: ${e.message}`);
    }
  }
};

使用示例

// 存储用户设置
await StorageService.setItem('userPreferences', {
  theme: 'dark',
  notifications: true,
  fontSize: 16
});

// 获取用户设置
const prefs = await StorageService.getItem('userPreferences');
console.log('用户主题:', prefs.theme);

// 获取所有存储键
const keys = await StorageService.getAllKeys();
console.log('存储的键名:', keys);

2.2 文件系统操作(react-native-fs)

对于大型文件存储需求,react-native-fs提供了完整的文件系统访问能力:

安装

npm install react-native-fs --save

核心功能实现

// storage/FileSystemService.js
import RNFS from 'react-native-fs';

export const FileSystemService = {
  /**
   * 获取应用沙盒目录路径
   * @returns {Promise<string>}
   */
  getDocumentDirectory: async () => {
    return RNFS.DocumentDirectoryPath;
  },

  /**
   * 写入文件
   * @param {string} filename - 文件名
   * @param {string} content - 文件内容
   * @param {boolean} [append=false] - 是否追加模式
   * @returns {Promise<boolean>} - 成功返回true
   */
  writeFile: async (filename, content, append = false) => {
    const path = `${RNFS.DocumentDirectoryPath}/${filename}`;
    return RNFS.writeFile(path, content, 'utf8', append);
  },

  /**
   * 读取文件内容
   * @param {string} filename - 文件名
   * @returns {Promise<string>} - 文件内容
   */
  readFile: async (filename) => {
    const path = `${RNFS.DocumentDirectoryPath}/${filename}`;
    return RNFS.readFile(path, 'utf8');
  },

  /**
   * 下载文件
   * @param {string} url - 下载URL
   * @param {string} filename - 保存文件名
   * @param {Function} onProgress - 进度回调函数
   * @returns {Promise<Object>} - 下载结果
   */
  downloadFile: async (url, filename, onProgress) => {
    const destinationPath = `${RNFS.DocumentDirectoryPath}/${filename}`;
    
    const downloadOptions = {
      fromUrl: url,
      toFile: destinationPath,
      background: true,
      discretionary: true,
      progress: (res) => {
        const progress = res.bytesWritten / res.contentLength;
        onProgress && onProgress(progress);
      }
    };

    try {
      const downloadResult = RNFS.downloadFile(downloadOptions).promise;
      return downloadResult;
    } catch (error) {
      console.error('文件下载失败:', error);
      throw error;
    }
  },

  /**
   * 获取目录下所有文件
   * @param {string} [directory=''] - 目录名,默认为文档根目录
   * @returns {Promise<Array<Object>>} - 文件列表
   */
  readDirectory: async (directory = '') => {
    const path = directory 
      ? `${RNFS.DocumentDirectoryPath}/${directory}` 
      : RNFS.DocumentDirectoryPath;
    
    return RNFS.readDir(path);
  },

  /**
   * 删除文件
   * @param {string} filename - 文件名
   * @returns {Promise<void>}
   */
  deleteFile: async (filename) => {
    const path = `${RNFS.DocumentDirectoryPath}/${filename}`;
    return RNFS.unlink(path);
  }
};

文件下载示例

// 下载大型PDF文件并显示进度
const downloadLargeFile = async () => {
  const fileUrl = 'https://example.com/large-document.pdf';
  const fileName = 'offline-document.pdf';
  
  try {
    await FileSystemService.downloadFile(
      fileUrl, 
      fileName,
      (progress) => {
        // 更新进度指示器
        setDownloadProgress(Math.round(progress * 100));
      }
    );
    
    showToast('文件下载完成');
    // 下载完成后可以读取文件路径进行预览
    const filePath = `${RNFS.DocumentDirectoryPath}/${fileName}`;
    openFilePreview(filePath);
  } catch (error) {
    showToast(`下载失败: ${error.message}`);
  }
};

三、云存储集成架构

3.1 REST API数据同步实现

API服务封装

// api/ApiService.js
import NetInfo from '@react-native-community/netinfo';

export const ApiService = {
  /**
   * 检查网络连接状态
   * @returns {Promise<boolean>} - 是否有网络连接
   */
  async isNetworkAvailable() {
    const netState = await NetInfo.fetch();
    return netState.isConnected && netState.isInternetReachable;
  },

  /**
   * 通用请求方法
   * @param {string} endpoint - API端点
   * @param {Object} options - 请求选项
   * @returns {Promise<Object>} - 响应数据
   */
  async request(endpoint, options = {}) {
    const baseUrl = 'https://api.yourdomain.com/v1';
    const url = `${baseUrl}${endpoint}`;
    
    // 默认请求头
    const headers = {
      'Content-Type': 'application/json',
      ...options.headers,
    };
    
    // 添加认证令牌
    const token = await StorageService.getItem('authToken');
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }
    
    try {
      const response = await fetch(url, {
        method: options.method || 'GET',
        headers,
        body: options.body ? JSON.stringify(options.body) : undefined,
        timeout: options.timeout || 30000,
      });
      
      if (!response.ok) {
        const errorData = await response.json().catch(() => null);
        throw new Error(errorData?.message || `HTTP错误: ${response.status}`);
      }
      
      return await response.json();
    } catch (error) {
      console.error(`API请求失败 [${endpoint}]:`, error.message);
      
      // 检查网络状态
      const isOnline = await this.isNetworkAvailable();
      if (!isOnline) {
        throw new Error('网络连接不可用,请检查您的网络设置');
      }
      
      throw error;
    }
  },
  
  // 数据模型API
  items: {
    /**
     * 获取项目列表
     * @param {Object} params - 查询参数
     * @returns {Promise<Array<Object>>} - 项目列表
     */
    async getList(params = {}) {
      const queryString = new URLSearchParams(params).toString();
      return ApiService.request(`/items${queryString ? `?${queryString}` : ''}`);
    },
    
    /**
     * 获取单个项目详情
     * @param {string} id - 项目ID
     * @returns {Promise<Object>} - 项目详情
     */
    async getById(id) {
      return ApiService.request(`/items/${id}`);
    },
    
    /**
     * 创建新项目
     * @param {Object} data - 项目数据
     * @returns {Promise<Object>} - 创建的项目
     */
    async create(data) {
      return ApiService.request('/items', {
        method: 'POST',
        body: data,
      });
    },
    
    /**
     * 更新项目
     * @param {string} id - 项目ID
     * @param {Object} data - 更新数据
     * @returns {Promise<Object>} - 更新后的项目
     */
    async update(id, data) {
      return ApiService.request(`/items/${id}`, {
        method: 'PUT',
        body: data,
      });
    },
    
    /**
     * 删除项目
     * @param {string} id - 项目ID
     * @returns {Promise<Object>} - 删除结果
     */
    async delete(id) {
      return ApiService.request(`/items/${id}`, {
        method: 'DELETE',
      });
    },
  },
};

3.2 离线优先同步系统设计

同步服务实现

// sync/SyncService.js
import { StorageService } from '../storage/AsyncStorageService';
import { ApiService } from '../api/ApiService';
import NetInfo from '@react-native-community/netinfo';

export const SyncService = {
  /**
   * 同步队列存储键
   */
  SYNC_QUEUE_KEY: 'offline_sync_queue',
  
  /**
   * 上次同步时间存储键
   */
  LAST_SYNC_KEY: 'last_sync_timestamp',
  
  /**
   * 添加操作到同步队列
   * @param {Object} operation - 操作对象
   * @param {string} operation.type - 操作类型 (CREATE/UPDATE/DELETE)
   * @param {string} operation.entity - 实体类型
   * @param {string} [operation.id] - 实体ID (UPDATE/DELETE时必填)
   * @param {Object} operation.data - 实体数据
   * @returns {Promise<void>}
   */
  async queueOperation(operation) {
    const queue = await StorageService.getItem(this.SYNC_QUEUE_KEY) || [];
    queue.push({
      ...operation,
      timestamp: Date.now(),
      uuid: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
    });
    await StorageService.setItem(this.SYNC_QUEUE_KEY, queue);
  },
  
  /**
   * 处理同步队列
   * @returns {Promise<Object>} - 同步结果
   */
  async processQueue() {
    // 检查网络连接
    const networkState = await NetInfo.fetch();
    if (!networkState.isConnected || !networkState.isInternetReachable) {
      return { success: false, error: '无网络连接', processed: 0 };
    }
    
    const queue = await StorageService.getItem(this.SYNC_QUEUE_KEY) || [];
    if (queue.length === 0) {
      return { success: true, processed: 0, message: '同步队列为空' };
    }
    
    let processedCount = 0;
    const failedOperations = [];
    
    // 按时间顺序处理队列
    for (const operation of queue) {
      try {
        switch (operation.type) {
          case 'CREATE':
            await ApiService[operation.entity].create(operation.data);
            break;
            
          case 'UPDATE':
            await ApiService[operation.entity].update(operation.id, operation.data);
            break;
            
          case 'DELETE':
            await ApiService[operation.entity].delete(operation.id);
            break;
            
          default:
            console.warn('未知操作类型:', operation.type);
            failedOperations.push(operation);
            continue;
        }
        
        processedCount++;
      } catch (error) {
        console.error(`同步操作失败 [${operation.type} ${operation.entity}]:`, error);
        failedOperations.push(operation);
        
        // 对于非致命错误,继续处理后续操作
        // 如果是认证错误等严重错误,跳出循环
        if (error.message.includes('认证') || error.message.includes('401')) {
          failedOperations.push(...queue.slice(processedCount + failedOperations.length));
          break;
        }
      }
    }
    
    // 保存失败的操作,用于下次重试
    await StorageService.setItem(this.SYNC_QUEUE_KEY, failedOperations);
    
    // 更新最后同步时间
    if (processedCount > 0) {
      await StorageService.setItem(this.LAST_SYNC_KEY, Date.now());
    }
    
    return {
      success: failedOperations.length === 0,
      processed: processedCount,
      failed: failedOperations.length,
      message: `${processedCount} 个操作成功, ${failedOperations.length} 个操作失败`
    };
  },
  
  /**
   * 执行完全同步(拉取服务器最新数据)
   * @param {string} entity - 实体类型
   * @param {Function} onProgress - 进度回调
   * @returns {Promise<Object>} - 同步结果
   */
  async fullSync(entity, onProgress) {
    try {
      const lastSyncTime = await StorageService.getItem(this.LAST_SYNC_KEY) || 0;
      const result = await ApiService[entity].getList({
        updatedSince: lastSyncTime
      });
      
      // 保存到本地存储
      await StorageService.setItem(`${entity}_list`, result.data);
      
      // 更新最后同步时间
      await StorageService.setItem(this.LAST_SYNC_KEY, Date.now());
      
      onProgress && onProgress(100); // 进度100%
      
      return {
        success: true,
        count: result.data.length,
        message: `成功同步 ${result.data.length} 条${entity}数据`
      };
    } catch (error) {
      console.error(`全量同步失败 [${entity}]:`, error);
      return {
        success: false,
        error: error.message
      };
    }
  },
  
  /**
   * 初始化同步服务
   * @returns {Promise<void>}
   */
  async initialize() {
    // 检查并创建同步队列(如果不存在)
    const queue = await StorageService.getItem(this.SYNC_QUEUE_KEY);
    if (!queue) {
      await StorageService.setItem(this.SYNC_QUEUE_KEY, []);
    }
    
    // 设置网络状态监听
    NetInfo.addEventListener(state => {
      if (state.isConnected && state.isInternetReachable) {
        console.log('网络已连接,尝试同步队列...');
        this.processQueue().then(result => {
          console.log('后台同步结果:', result);
        });
      }
    });
  }
};

同步服务使用流程

// 在应用启动时初始化同步服务
SyncService.initialize();

// 创建数据时同时添加到同步队列
const createItem = async (data) => {
  // 1. 保存到本地存储
  const localItems = await StorageService.getItem('items_list') || [];
  const newItem = { ...data, id: generateLocalId(), isPendingSync: true };
  localItems.push(newItem);
  await StorageService.setItem('items_list', localItems);
  
  // 2. 添加到同步队列
  await SyncService.queueOperation({
    type: 'CREATE',
    entity: 'items',
    data: newItem
  });
  
  // 3. 尝试立即同步(如果在线)
  const networkState = await NetInfo.fetch();
  if (networkState.isConnected && networkState.isInternetReachable) {
    await SyncService.processQueue();
  }
  
  return newItem;
};

// 手动触发全量同步
const triggerFullSync = async () => {
  setSyncStatus('正在同步数据...');
  setSyncProgress(0);
  
  try {
    const result = await SyncService.fullSync('items', (progress) => {
      setSyncProgress(progress);
    });
    
    if (result.success) {
      setSyncStatus(`同步成功: ${result.message}`);
      // 刷新UI显示最新数据
      loadItemsFromStorage();
    } else {
      setSyncStatus(`同步失败: ${result.error}`);
    }
  } catch (error) {
    setSyncStatus(`同步出错: ${error.message}`);
  } finally {
    setTimeout(() => setSyncStatus(''), 3000);
  }
};

四、高级应用:离线优先笔记应用架构

4.1 系统架构设计

mermaid

4.2 核心实现代码

笔记服务实现

// services/NoteService.js
import { StorageService } from '../storage/AsyncStorageService';
import { FileSystemService } from '../storage/FileSystemService';
import { SyncService } from '../sync/SyncService';
import { v4 as uuidv4 } from 'uuid';

export const NoteService = {
  /**
   * 生成本地ID
   * @returns {string} - 本地唯一ID
   */
  generateLocalId() {
    return `local_${uuidv4()}`;
  },
  
  /**
   * 获取所有笔记
   * @param {Object} options - 查询选项
   * @param {boolean} [options.includePendingSync=false] - 是否包含待同步项
   * @returns {Promise<Array<Object>>} - 笔记列表
   */
  async getAllNotes(options = {}) {
    const notes = await StorageService.getItem('notes_list') || [];
    
    // 过滤掉已删除的笔记
    let result = notes.filter(note => !note.isDeleted);
    
    // 如果不包含待同步项,则过滤掉
    if (!options.includePendingSync) {
      result = result.filter(note => !note.isPendingSync);
    }
    
    // 按更新时间降序排序
    return result.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
  },
  
  /**
   * 获取单个笔记
   * @param {string} id - 笔记ID
   * @returns {Promise<Object|null>} - 笔记对象或null
   */
  async getNoteById(id) {
    const notes = await StorageService.getItem('notes_list') || [];
    const note = notes.find(n => n.id === id);
    
    if (!note || note.isDeleted) return null;
    
    // 如果有富文本内容,从文件系统加载
    if (note.hasRichContent) {
      try {
        note.content = await FileSystemService.readFile(`notes/${note.id}.md`);
      } catch (error) {
        console.error('读取笔记内容失败:', error);
        note.content = note.content || '无法加载笔记内容';
      }
    }
    
    return note;
  },
  
  /**
   * 创建新笔记
   * @param {Object} noteData - 笔记数据
   * @param {string} noteData.title - 标题
   * @param {string} noteData.content - 内容
   * @param {boolean} [noteData.hasRichContent=false] - 是否为富文本
   * @param {Array<string>} [noteData.tags=[]] - 标签
   * @returns {Promise<Object>} - 创建的笔记
   */
  async createNote(noteData) {
    const newNote = {
      id: this.generateLocalId(),
      title: noteData.title,
      content: noteData.content,
      tags: noteData.tags || [],
      hasRichContent: noteData.hasRichContent || false,
      isPendingSync: true,
      isDeleted: false,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    };
    
    // 获取现有笔记列表
    const notes = await StorageService.getItem('notes_list') || [];
    notes.push(newNote);
    
    // 保存笔记元数据到AsyncStorage
    await StorageService.setItem('notes_list', notes);
    
    // 如果是富文本,保存内容到文件系统
    if (newNote.hasRichContent) {
      await FileSystemService.writeFile(
        `notes/${newNote.id}.md`, 
        newNote.content
      );
      // 清空内存中的内容,节省内存
      newNote.content = '[富文本内容 - 从文件加载]';
    }
    
    // 添加到同步队列
    await SyncService.queueOperation({
      type: 'CREATE',
      entity: 'notes',
      data: newNote
    });
    
    // 尝试立即同步
    await SyncService.processQueue();
    
    return newNote;
  },
  
  /**
   * 更新笔记
   * @param {string} id - 笔记ID
   * @param {Object} updates - 更新数据
   * @returns {Promise<Object>} - 更新后的笔记
   */
  async updateNote(id, updates) {
    const notes = await StorageService.getItem('notes_list') || [];
    const index = notes.findIndex(n => n.id === id);
    
    if (index === -1) {
      throw new Error(`找不到ID为 ${id} 的笔记`);
    }
    
    // 合并更新数据
    const updatedNote = {
      ...notes[index],
      ...updates,
      updatedAt: new Date().toISOString(),
      isPendingSync: true
    };
    
    notes[index] = updatedNote;
    
    // 保存元数据
    await StorageService.setItem('notes_list', notes);
    
    // 如果更新了内容且是富文本,更新文件
    if (updates.content && updatedNote.hasRichContent) {
      await FileSystemService.writeFile(
        `notes/${updatedNote.id}.md`, 
        updates.content
      );
      // 如果返回更新后的笔记,清空内容字段
      updatedNote.content = '[富文本内容 - 从文件加载]';
    }
    
    // 添加到同步队列
    await SyncService.queueOperation({
      type: 'UPDATE',
      entity: 'notes',
      id: updatedNote.id,
      data: updatedNote
    });
    
    // 尝试立即同步
    await SyncService.processQueue();
    
    return updatedNote;
  },
  
  /**
   * 删除笔记
   * @param {string} id - 笔记ID
   * @returns {Promise<boolean>} - 操作结果
   */
  async deleteNote(id) {
    const notes = await StorageService.getItem('notes_list') || [];
    const index = notes.findIndex(n => n.id === id);
    
    if (index === -1) {
      throw new Error(`找不到ID为 ${id} 的笔记`);
    }
    
    // 软删除:标记为已删除,而不是实际删除
    notes[index].isDeleted = true;
    notes[index].isPendingSync = true;
    notes[index].updatedAt = new Date().toISOString();
    
    await StorageService.setItem('notes_list', notes);
    
    // 添加到同步队列
    await SyncService.queueOperation({
      type: 'DELETE',
      entity: 'notes',
      id: id
    });
    
    // 尝试立即同步
    await SyncService.processQueue();
    
    return true;
  }
};

五、性能优化与最佳实践

5.1 存储性能优化策略

  1. 数据分层存储

    • 元数据和小型数据:AsyncStorage
    • 大型二进制数据:文件系统
    • 敏感数据:加密存储
  2. 查询优化

    // 优化前:每次查询都遍历整个数组
    const getNotesByTag = (tag) => {
      const notes = await StorageService.getItem('notes_list');
      return notes.filter(note => note.tags.includes(tag));
    };
    
    // 优化后:维护标签索引
    const buildTagIndex = async () => {
      const notes = await StorageService.getItem('notes_list');
      const tagIndex = {};
    
      notes.forEach(note => {
        note.tags.forEach(tag => {
          if (!tagIndex[tag]) tagIndex[tag] = [];
          tagIndex[tag].push(note.id);
        });
      });
    
      await StorageService.setItem('tag_index', tagIndex);
    };
    
    // 使用索引查询
    const getNotesByTagOptimized = async (tag) => {
      const tagIndex = await StorageService.getItem('tag_index') || {};
      const noteIds = tagIndex[tag] || [];
    
      if (noteIds.length === 0) return [];
    
      const notes = await StorageService.getItem('notes_list');
      return notes.filter(note => noteIds.includes(note.id) && !note.isDeleted);
    };
    
  3. 批量操作

    // 批量保存笔记,减少I/O操作
    async function batchSaveNotes(notes) {
      // 1. 先保存所有富文本内容到文件系统
      const filePromises = notes
        .filter(note => note.hasRichContent && note.content)
        .map(note => 
          FileSystemService.writeFile(
            `notes/${note.id}.md`, 
            note.content
          )
        );
    
      // 并行处理文件写入
      await Promise.all(filePromises);
    
      // 2. 清空内容字段节省存储空间
      const notesForStorage = notes.map(note => 
        note.hasRichContent 
          ? { ...note, content: '[富文本内容 - 从文件加载]' } 
          : note
      );
    
      // 3. 批量保存元数据
      await StorageService.setItem('notes_list', notesForStorage);
    }
    

5.2 错误处理与恢复机制

// storage/ErrorHandling.js
export const StorageErrorTypes = {
  NETWORK_ERROR: 'NETWORK_ERROR',
  STORAGE_FULL: 'STORAGE_FULL',
  AUTH_ERROR: 'AUTH_ERROR',
  CONFLICT_ERROR: 'CONFLICT_ERROR',
  FILE_NOT_FOUND: 'FILE_NOT_FOUND',
  UNSUPPORTED_OPERATION: 'UNSUPPORTED_OPERATION',
  GENERIC_ERROR: 'GENERIC_ERROR'
};

export const ErrorHandler = {
  /**
   * 分类错误类型
   * @param {Error} error - 错误对象
   * @returns {Object} - 分类后的错误信息
   */
  classifyError(error) {
    if (!error) {
      return {
        type: StorageErrorTypes.GENERIC_ERROR,
        message: '未知错误',
        originalError: error
      };
    }
    
    // 根据错误消息分类
    if (error.message.includes('网络') || error.message.includes('offline')) {
      return {
        type: StorageErrorTypes.NETWORK_ERROR,
        message: '网络连接错误,请检查网络设置',
        originalError: error
      };
    }
    
    if (error.message.includes('storage') || error.message.includes('full')) {
      return {
        type: StorageErrorTypes.STORAGE_FULL,
        message: '存储空间不足,请清理空间后重试',
        originalError: error
      };
    }
    
    if (error.message.includes('认证') || error.message.includes('401')) {
      return {
        type: StorageErrorTypes.AUTH_ERROR,
        message: '认证失败,请重新登录',
        originalError: error
      };
    }
    
    if (error.message.includes('conflict') || error.message.includes('409')) {
      return {
        type: StorageErrorTypes.CONFLICT_ERROR,
        message: '数据冲突,请解决冲突后重试',
        originalError: error
      };
    }
    
    if (error.message.includes('not found') || error.message.includes('404')) {
      return {
        type: StorageErrorTypes.FILE_NOT_FOUND,
        message: '文件不存在或已被删除',
        originalError: error
      };
    }
    
    return {
      type: StorageErrorTypes.GENERIC_ERROR,
      message: error.message || '操作失败',
      originalError: error
    };
  },
  
  /**
   * 错误恢复策略
   * @param {Object} errorInfo - 分类后的错误信息
   * @param {Function} retryAction - 重试函数
   * @returns {Promise<Object>} - 恢复结果
   */
  async handleRecovery(errorInfo, retryAction) {
    switch (errorInfo.type) {
      case StorageErrorTypes.NETWORK_ERROR:
        // 网络错误:等待网络恢复后重试
        return new Promise((resolve) => {
          const unsubscribe = NetInfo.addEventListener(state => {
            if (state.isConnected && state.isInternetReachable) {
              unsubscribe();
              retryAction().then(resolve).catch(resolve);
            }
          });
          
          // 设置超时,5分钟后放弃
          setTimeout(() => {
            unsubscribe();
            resolve({ 
              success: false, 
              error: '网络仍不可用,已取消重试' 
            });
          }, 5 * 60 * 1000);
        });
        
      case StorageErrorTypes.STORAGE_FULL:
        // 存储满:尝试清理缓存
        await this.clearCache();
        return retryAction();
        
      case StorageErrorTypes.AUTH_ERROR:
        // 认证错误:触发重新登录流程
        AuthService.logout();
        NavigationService.navigate('Login', { needRelogin: true });
        throw errorInfo; // 不重试,需要用户干预
        
      case StorageErrorTypes.CONFLICT_ERROR:
        // 冲突错误:调用冲突解决策略
        return ConflictResolver.resolve(errorInfo, retryAction);
        
      default:
        // 其他错误:简单重试3次
        for (let i = 0; i < 3; i++) {
          try {
            await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
            const result = await retryAction();
            return result;
          } catch (retryError) {
            if (i === 2) throw retryError; // 最后一次失败抛出错误
          }
        }
    }
  },
  
  /**
   * 清理缓存释放空间
   * @returns {Promise<boolean>} - 是否清理成功
   */
  async clearCache() {
    try {
      // 1. 删除30天前的缓存文件
      const cacheDir = await FileSystemService.getDocumentDirectory('cache');
      const files = await FileSystemService.readDirectory(cacheDir);
      
      const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
      
      for (const file of files) {
        if (file.mtime < thirtyDaysAgo) {
          await FileSystemService.deleteFile(file.path);
        }
      }
      
      // 2. 清理已删除但保留的笔记文件
      const notes = await StorageService.getItem('notes_list') || [];
      const validNoteIds = new Set(notes.filter(n => !n.isDeleted).map(n => n.id));
      
      const noteFiles = await FileSystemService.readDirectory('notes');
      for (const file of noteFiles) {
        const noteId = file.name.replace('.md', '');
        if (!validNoteIds.has(noteId)) {
          await FileSystemService.deleteFile(file.path);
        }
      }
      
      return true;
    } catch (error) {
      console.error('清理缓存失败:', error);
      return false;
    }
  }
};

六、总结与未来趋势

React Native的存储方案正朝着离线优先无缝同步的方向发展。随着Web标准的普及,我们看到越来越多的Web API被引入React Native生态,如File System Access API和Background Sync API。同时,新兴的存储技术如Watermelon DB提供了更强大的本地数据库能力,结合GraphQL订阅可以实现毫秒级的实时数据同步。

未来的移动应用存储架构将更加注重:

  1. 边缘计算与本地智能处理
  2. 端到端加密的全链路安全
  3. 增量同步冲突自动解决
  4. 持久化UI状态离线首屏渲染

作为开发者,我们需要根据项目规模和需求选择合适的存储方案,同时保持对新兴技术的关注,构建既满足当前需求又具备未来扩展性的存储系统。

通过本文介绍的存储方案和最佳实践,您应该能够构建一个可靠、高效且用户友好的React Native应用数据存储系统,为用户提供流畅的离线体验和无缝的跨设备同步能力。

附录:常用存储库与资源

库名称功能描述GitHub星数适用场景
@react-native-async-storage/async-storage异步键值存储5.8k+简单数据、用户设置
react-native-fs文件系统访问5.9k+大型文件、二进制数据
react-native-keychain安全存储4.7k+密码、令牌、敏感信息
react-native-sqlite-storageSQLite数据库5.3k+复杂查询、关系数据
realm移动端数据库12.9k+高性能本地数据库
watermelondb高级离线数据库2.7k+复杂离线同步应用
redux-persistRedux状态持久化12.8k+Redux应用状态存储
mobx-persistMobX状态持久化1.1k+MobX应用状态存储

【免费下载链接】react-native 一个用于构建原生移动应用程序的 JavaScript 库,可以用于构建 iOS 和 Android 应用程序,支持多种原生移动平台,如 iOS,Android,React Native 等。 【免费下载链接】react-native 项目地址: https://gitcode.com/GitHub_Trending/re/react-native

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值