ReactNative實現鍵值對的同步存取

ReactNative實現鍵值對的同步存取

官方 AsyncStorage

  • AsyncStorage 是一個簡單的、異步的、持久化的 Key-Value 存儲系統。
  • 由於是異步的,每個方法都需要返回一個 Promise,不滿足同步存取需求。
  • 它的使用請參考官方實例

實現同步存取的兩種方案

使用靜態對象持有

  • 思路分析:

    • 在App啓動時,從 AsyncStorage 中異步讀取所有鍵值對,並賦值給靜態變量;
    • 調用 setValue(key) 時先將其加入到靜態變量中,之後再異步存入 AsyncStorage;
    • 調用 getValue(key) 時直接從靜態變量中讀取,實現同步存取;
  • 優缺點分析:

    • 優點:代碼實現量少,不需要引入其他第三方庫做支撐,存儲任務實際上仍舊由系統提供的 AsyncStorage 完成。
    • 缺點:由於第一步的 init 讀取所有鍵值對仍然是異步操作,所以需要在 App 初始化時完成這一操作,並且在初始化時不能執行同步讀取,因爲此時可能靜態變量可能並未賦值成功。
  • 代碼實現:

    
    export default class SyncStorage {
    
        static cache: { [key: string]: string } = {}
    
        // 初始化需要在App啓動時執行
        static async init() {
            let keys = await AsyncStorage.getAllKeys()
            let items = await AsyncStorage.multiGet(keys).then()
            items.map(([key, value]) => {
                this.cache[key] = value
            })
        }
    
        static getValue(key: string) {
            return this.cache[key]
        }
    
        static setValue(key: string, value: string) {
            if (this.cache[key] === value) return
            this.cache[key] = value
            AsyncStorage.setItem(key, value)
        }
    
        static removeKey(key: string) {
            delete this.cache[key]
            AsyncStorage.removeItem(key)
        }
    }

使用realm.js自行封裝

  • 思路分析:

    • 由於我們經常有一些需求是在 App 初始化時就要進行 Key-Value 的讀取,從而選擇UI上的展示內容,所以上面的靜態變量持有的方案,並不能滿足這種需求。
    • 通過閱讀 react-native AsyncStorage 部分的Android實現源碼可以發現,facebook 使用了 SQLiteDatabase 來實現 Key-Value 的存取,那麼我們也可以自己使用數據庫實現一套簡單的鍵值對存取方案。
    • 由於 realm 提供了 ReactNative 版本,集成更加簡單高效,所以這裏使用 realm 來完成這套方案。
  • 代碼實現:

    • 使用 realm 實現存取操作

      /**
       * 定義Key-Value類
       */
      class Config {
      
          private _key: string
          private _value: string
      
          constructor(key: string, value: string) {
              this._key = key
              this._value = value
          }
      
          get key(): string {
              return this._key
          }
      
          get value(): string {
              return this._value
          }
      }
      
      /**
       * 定義Realm-Schema
       */
      const ConfigSchema = {
          name: Config.name,
          primaryKey: 'key',
          properties: {
          key: 'string',
          value: 'string'
          }
      } 
      
      // 獲取 realm 存取對象
      const realm = new Realm({schema: [ConfigSchema, MediaSchema]})
      
      /**
       * 使用 realm 實現 Key-Value 存取
       */
      class DBManager {
      
          static insertConfig(config: Config) {
              realm.write(() => {
                  realm.create(Config.name, config)
              })
          }
      
          static updateConfig(config: Config) {
              realm.write(() => {
                  realm.create(Config.name, config, true)
              })
          }
      
          static queryConfig(key: string): Config {
              return realm.objectForPrimaryKey<Config>(Config.name, key)!
          }
      }
      
      /**
       * 封裝存取 Util,供外界調用
       */
      export default class SyncStorage {
      
          static putValue(key: string, value: string) {
              if (DBManager.queryConfig(key) == undefined)
                  DBManager.insertConfig(new Config(key, value))
              else
                  DBManager.updateConfig(new Config(key, value))
              }
      
          static getValue(key: string): string | undefined {
              let config: Config = DBManager.queryConfig(key)
              return config == undefined ? undefined : config.value
          }
      }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章