如何解决HarmonyOS鸿蒙Next中通过自定义数据库管理组件从键值对数据库获取数据失败的问题
如何解决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/await来保证每个调用的正确时序。
问题代码如下:
// 获取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,实现同步逻辑代码顺序。
更多关于如何解决HarmonyOS鸿蒙Next中通过自定义数据库管理组件从键值对数据库获取数据失败的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于如何解决HarmonyOS鸿蒙Next中通过自定义数据库管理组件从键值对数据库获取数据失败的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,通过自定义数据库管理组件从键值对数据库获取数据失败,可能涉及以下原因及解决方法:
-
数据库路径或名称错误:确保数据库路径和名称正确,使用
DatabaseHelper
或DatabaseManager
时,路径和名称需与创建时一致。 -
键值对不存在或键名错误:检查键名是否正确,使用
getString
、getInt
等方法时,确保键名与存储时一致。 -
数据库未初始化或未打开:在操作数据库前,确保已调用
openOrCreateDatabase
或getDatabase
方法初始化并打开数据库。 -
权限问题:检查应用是否具备访问数据库的权限,确保在
config.json
中正确配置了ohos.permission.READ_USER_STORAGE
和ohos.permission.WRITE_USER_STORAGE
权限。 -
数据库版本不匹配:如果数据库版本升级,需在
onUpgrade
方法中处理数据迁移,确保数据兼容。 -
异步操作问题:如果使用异步操作,确保在回调中正确处理数据获取逻辑,避免因异步未完成导致数据获取失败。
-
数据库损坏:如果数据库文件损坏,可能导致数据获取失败,可通过备份恢复或重新创建数据库解决。
-
日志排查:使用
HiLog
或console.log
输出日志,检查操作步骤和错误信息,定位问题。
通过以上步骤,可排查并解决从键值对数据库获取数据失败的问题。