HarmonyOS 鸿蒙Next 如何解决通过自定义数据库管理组件从键值对数据库获取数据失败的问题 鸿蒙场景化案例

发布于 1周前 作者 sinazl 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 如何解决通过自定义数据库管理组件从键值对数据库获取数据失败的问题 鸿蒙场景化案例

【问题现象】

自定义了一个数据库管理组件,封装了对分布式键值对数据库组件的常用操作。在页面的aboutToAppear回调方法中,通过先请求网络获取一些数据,并通过自定义管理组件存入键值对数据库后,获取失败。

交互过程如下:

但是,现在通过打印的日志的信息,可以看到实际交互的过程。在调用自定义数据库管理组件创建kvStore实例后,自定义组件成功获取到kvStore实例的时序晚于存入和获取数据交互之后。这导致,在存入数据时,kvStore的实例尚未完成初始化,从而为undefined。

【背景知识】

  • 异步并发:sync/await是一种用于处理异步操作的Promise语法糖,使得编写异步代码变得更加简单和易读。
  • KVManager:分布式键值数据库管理实例,用于获取数据库的相关信息。
  • SingleKVStore:单版本分布式键值数据库,不对数据所属设备进行区分,提供查询数据和同步数据的方法。

【定位思路】

(1)查看现有代码实现,主页面中调用自定义组件的交互。

问题代码如下:

async aboutToAppear(): Promise<void> {
  console.log('==>开始获取kvManger实例及获取数据')
  console.log('==>MainPage之后');
  let myStore: myKV = new myKV()
  console.log('==>step1,调用createMyKVManager,创建KVManager实例')
  await myStore.createMyKVManager()
  console.log('==>step2,调用getMyKVStore,获取kvStore的实例')
  await myStore.getMyKVStore()
  console.log('==>step3, 调用putData,向kvStore的实例写入数据')
  await myStore.PutData("data", '这是一条测试数据')
  console.log('==>step4,调用getData,从kvStore的实例中获取数据')
  await myStore.GetData('data', (res: string) => {
    console.log('==>step4 调用getData获取的结果:' + res)
  })
}

(2)可以看到在调用所有的自定义数据库管理组件方法时,都加入了await。其本意是期望能够通过async/awit来保证每个调用的正确时序。

问题代码如下:

// 获取KVManager管理对象
getMyKVStore() {
  try {
    const options: distributedKVStore.Options = {
      createIfMissing: true,
      encrypt: false,
      backup: false,
      autoSync: true,
      kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
      securityLevel: distributedKVStore.SecurityLevel.S2,
    };
    if (this.kvManager) {
      // 使用callBack的方式来获取kvStore的实例
      this.kvManager.getKVStore('storeId', options, (err: BusinessError, store: distributedKVStore.SingleKVStore) => {
        if (err) {
          console.error(`Failed to get KVStore.code is ${err.code},message is ${err.message}`);
          return;
        }
        console.info("====>Succeeded in getting KVStore");
        this.kvStore = store;
      });
    }
  } catch (e) {
    let error = e as BusinessError;
    console.error(`An unexpected error occurred.code is ${error.code},message is ${error.message}`);
    console.log(`====>An unexpected error occurred.code is ${error.code},message is ${error.message}`);
  }
}

在自定义的数据库管理组件中,创建kvStore实例方法中使用的是callBack回调的方式(第13至23行)。但是,AsyncCallback异步回调函数并不会受await影响,因为async/await需要一起搭配使用。 所以即使使用了await,该代码逻辑还是异步执行,并不会等待回调函数执行完成。所以出现调用时序并没有按照预期的进行,出现了kvStore实例为undefined的现象。

【解决方案】

(1)按照上述分析,使用callBack的方式无法保证调用的时序。

(2)因此,这里可以改为使用Promise异步回调的方式,并通过async/await处理异步操作的Promise,从而保证交互时序按照预期进行。

getMyKVStore方法修改后代码(使用的是方法二,以下案例当中的第12行):

代码示例如下:

async getMyKVStore() {
  try {
    const options: distributedKVStore.Options = {
      createIfMissing: true,
      encrypt: false,
      backup: false,
      autoSync: true,
      kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
      securityLevel: distributedKVStore.SecurityLevel.S2,
    };
    if (this.kvManager) {
      // 改为使用Promise回调的方式,并增加async/await来保证异步回调执行结束返回。在async函数内部,使用await关键字等待一个Promise对象的解析,并返回其解析值
      this.kvStore = await this.kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options);
      console.info("====>Succeeded in getting KVStore");
    }
  } catch (e) {
    let error = e as BusinessError;
    console.error(`An unexpected error occurred.code is ${error.code},message is ${error.message}`);
    console.log(`====>An unexpected error occurred.code is ${error.code},message is ${error.message}`);
  }
}

同理,kvStore实例的put和get操作同样采用上面相同的处理方式。即,使用async/await和对应的Promise异步回调函数保证整体的执行时序(上述代码第12至17行)。

改造完成后正常存取值:

【总结】

  • 设置并获取分布式数据库对象的方法ArkTS提供了两种,一种是通过AsyncCallback异步回调函数的形式进行异步创建; 另外一种则是利用了Promise作为返回值;
  • 相较于AsyncCallback的异步回调方式,Promise会显得代码更加灵活,代码可读性更高,并且Promise可以搭配async/await,实现同步逻辑代码顺序。
1 回复

作为IT专家,对于HarmonyOS 鸿蒙Next中通过自定义数据库管理组件从键值对数据库获取数据失败的问题,可以从以下几个方面进行排查和解决:

  1. 数据库初始化:确保在应用启动时正确初始化了键值对数据库,并且数据库实例在应用生命周期中持续有效。
  2. 键值一致性:验证存储与读取时使用的键是否完全一致,任何不匹配都可能导致数据获取失败。
  3. 权限检查:检查应用是否有足够的权限去读写键值对数据库。权限不足会导致数据访问失败。
  4. 数据同步:如果使用了分布式键值对数据库,确保同步机制已正确配置并正在工作,数据未同步也会导致读取失败。
  5. 异常处理:增加适当的异常捕获和处理逻辑,以捕获并处理在存储或读取数据时可能发生的错误,有助于定位问题。
  6. 清理缓存:尝试清理应用缓存或重新安装应用,以解决可能的缓存问题导致的读取失败。

如果以上步骤都确认无误但问题依旧存在,可能涉及更复杂的底层问题或特定场景的bug。此时,建议详细记录错误日志和操作步骤,以便进一步分析。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部