本周开始对接新需求电力交易系统安徽部分,开了需求评审会,同时发现上个版本存在线上问题,进行了修复
1.await 等待的内容失败时会阻塞代码
如下所示,通过setloading控制页面的loading效果,但是当res的await等不到结果时,因为代码发生了阻塞,setloading(false)未执行,页面就会一直处于loading状态
// 中长期交易统计 查询
const submitCallback = useCallback(async (date) => {
setloading(true);
const params = {
startDate: moment(date[0]).format(FORMATTIME),
endDate: moment(date[1]).format(FORMATTIME),
tradeCenterId: 1,
};
const res = await getLongTrade(params);//这里请求失败时会阻塞
setData(res?.data);
setloading(false);
本地测试:
执行成功的结果如下,new Promise相当于直接执行了Promise构造函数,因此返回的test1是一个Promise对象,await等待到了test成功的结果resolve中的值
const test1 = new Promise((resolve, reject) => {
resolve('执行成功,这是成功的结果')
})
const handleAwait1 = async () => {
const res = await test1
console.log(res) //执行成功,这是成功的结果
console.log('执行这行代码表示未阻塞')//执行这行代码表示未阻塞
}
handleAwait1()
可是执行失败时却发生了阻塞:
const test2 = new Promise((resolve, reject) => {
reject('执行失败,这是执行失败的结果')
})
const handleAwait2 = async () => {
const res2 = await test2
console.log(res2)
console.log('执行这行代码表示未阻塞')//代码未执行
}
handleAwait2()
控制台报未捕获错误,此时若想要代码走下去,需要添加catch捕获错误:
const test2 = new Promise((resolve, reject) => {
reject('执行失败,这是执行失败的结果')
})
const handleAwait2 = async () => {
const res2 = await test2.catch(err => {
console.log(err, '执行失败了,没关系,站起来继续往下走吧!')
})//添加catch捕获一下错误即可
console.log(res2)
console.log('执行这行代码表示未阻塞')
}
handleAwait2()
回到一开始的loading问题,代码只需进行如下修改,即可恢复正常loading效果:
// 中长期交易统计 查询
const submitCallback = useCallback(async (date) => {
setloading(true);
const params = {
startDate: moment(date[0]).format(FORMATTIME),
endDate: moment(date[1]).format(FORMATTIME),
tradeCenterId: 1,
};
const res = await getLongTrade(params).catch(()=>{ setloading(false) })
setData(res?.data);
setloading(false);
2.undefined转换为数字会是NaN,不管是隐式还是显式转换
console.log(undefined == null) //true
console.log(undefined === null) //false
console.log(null + 5) //5
console.log(undefined + 5) //NaN
console.log(Number(null)) //0
console.log(Number(undefined)) //NaN
此处容易踩坑的地方在于,项目中我们未来不报错,经常会使用可选链操作符"?.",正常使用还好,但是当进行"+, -, * ,/"等数学计算时,会导致错误,此时的null和undefined运算结果是不同的,如果要拿num再去做进一步的展示或计算,就会报错
const obj = {
key1: 1,
key2: undefined,
key3: null,
key4: 3
}
const num = obj?.key5 + 1
console.log(num)//2 NaN 1 4
3.??操作符的运算优先级低于"+"和"-"
当使用??进行计算时,与数学运算符连用时,注意添加(),提高优先级,否则会出现意想不到的结果
const obj = {
a: {
key: [1, 2, 0]
}
}
const x = (obj?.a?.key?.[2] ?? 0) - 5 //找得到加括号,提高优先级
const x2 = obj?.a?.key?.[2] ?? 0 - 5 //找得到加括号,未提高优先级,其实先进行了"0 - 5"部分的计算
const x3 = obj?.a?.key?.[4] ?? 0 - 5 //找不到
console.log(x)
console.log(x2)
console.log(x3)
4.antd组件的性能非常差
antd组件数据一多就卡,因此不管使用何种组件,一定要注意每次展示少量的数据,比如10条或20条等,比如对表格进行分页等。本次项目中,有大量的表格数据渲染,因产品经理不允许分页,导致页面卡顿,以后做项目除非产品经理明确要求,一定要有分页意识。关于antd,组件性能差,详见链接:为什么Ant-Design的Table性能这么低? - 知乎
5.for in 和 for of
对象:
for in 遍历对象及其原型链上的属性,for of 不可遍历对象
const obj = {
key1: 1,
key2: undefined,
key3: null,
key4: 3
}
obj.__proto__ = {
proto: 'proto method'
}
for (let key in obj) {
console.log(obj?.[key])
}
使用for of 遍历 对象会报错:
const obj = {
key1: 1,
key2: undefined,
key3: null,
key4: 3
}
obj.__proto__ = {
proto: 'proto method'
}
for (let key of obj) { //不可遍历
console.log(obj?.[key])
}
若只想遍历对象自身属性可以遍历Object.keys()
const obj = {
key1: 1,
key2: undefined,
key3: null,
key4: 3
}
obj.__proto__ = {
proto: 'proto method'
}
for (let key of Object.keys(obj)) {
console.log(key)
}
数组:
for of 遍历数组,使用for in 遍历数组时,得到的是数组的索引
const arr = [5, 4, 3, 2]
for (let val of arr) {
console.log(val)
}
const arr = [5, 4, 3, 2]
for (let val in arr) {
console.log(val)
}