前言:
在实际开发中,经常遇到一些细节的点,可能在出现问题时,看代码逻辑,没有任何问题,但是运行结果就是不符合预期,本节将梳理一些这样的问题点,希望能帮助到大家
一、number类型数据json解析后,被截断,导致逻辑错误
如果我们从后台接口返回的数据类型是一个long类型,比如一个id,而端侧定义的类型为number类型时,在进行json解析时,可能会出现精度丢失问题,如下通过JSON.parse解析时,实际解析获取的id=12345678901234567000,与实际不符,从而导致后续逻辑异常
let tmp = JSON.parse('{"name":"name","id":12345678901234567890}')
解决方案
1、如果后台接口返回的是string类型,端侧也用string类型接收
2、如果后台接口返回的本身就是long类型,可以使用三方库json-bigint做json解析,接收使用bigint类型接收,代码示例如下
OpenHarmony三方库中心仓https://ohpm.openharmony.cn/#/cn/detail/@ohmos%2Fjson-bigint
let tmp1 = JsonBigInt.parse('{"name":"name","id":12345678901234567890}') as Person;
console.log(`${tmp1.id}`)
class Person {
name:string = ''
id:bigint =BigInt(0)
}
二、map的json序列化是空字符串(包括set)
JSON.stringify()是js语法,在ArkTS中仅支持特定类型的json转换。我们可以通过如下方法解决
1、将Map转为Record,然后对Record对象进行JSON.stringify转换获取json字符串
mapToRecord(map: Map<string, Object>): Record<string, Object> {
let ret: Record<string, Object> = {}
map.forEach((val, key) => {
ret[key] = val
})
return ret;
}
2、直接用Record对象替换map来使用
let ret: Record<string, Object> = {"name":"name","id": 1}
console.log(JSON.stringify(ret))
三、如何遍历Enum枚举值
我们可能和后台交互时,会根据接口返回的枚举key,查询对应的value值等等场景,会需要遍历枚举的场景,可以参考如下:
enum MyEnum {
'A' = 'a',
'B' = 'b'
}
function test() {
let enumKeys = Object.keys(MyEnum).filter(key => isNaN(Number(key)));
let enumVals = enumKeys.map(key => MyEnum[key as keyof object])
console.log("keys:", enumKeys) // keys: A,B
console.log("vals:", enumVals) // vals: a,b
}
四、try catch中e对象的类型,如何打印异常信息,有时候直接打印json序列化为空,可以参考如下打印,如果要打印堆栈信息可以转为BusinessError对象
async print() {
try {
let a = await this.test({"name":new Person()})
return a
} catch (e) {
console.log(`error: ${e}`)
console.log(`error json: ${JSON.stringify(e)}`)
console.log(`error code: ${(e as BusinessError).code}`)
console.log(`error message: ${(e as BusinessError).message}`)
console.log(`error stack: ${(e as BusinessError).stack}`)
}
return 1
}
如上构造了一个空指针异常,打印异常如下:
五、setTimeout,setInterval启动后定时任务没生效
解决方法:setTimeout,setInterval的默认id不要设置为0,需要设置为-1
在开发过程中,有时候我们会发现,我们设置的setTimeout或者setInterval定时任务没有生效,但是明明代码里已经启动了定时任务。这里有个注意点,就是定时任务的id都是从0开始的,如果我们app有如下的逻辑,在启动一个定时任务时,会先清除下上次启动的任务,如果这里保存的全局id默认是0的话,可能会误把其他地方启动的定时任务给清除掉,导致任务没执行。所以我们的默认id初始值需要赋值为-1。另外还有一点就是clearTimeout和clearInterval会互相清除,这也是一个注意点,不知道后续鸿蒙的系统版本会不会修复这个问题。
id1 = 0
id2 = 0
test1() {
clearTimeout(this.id1)
let id1 = setTimeout(() => {
console.log('')
})
clearInterval(this.id2)
let id2 = setInterval(() => {
console.log('')
}, 1000)
}