【工作总结】2023.11第二周

79 阅读4分钟

本周开始对接新需求电力交易系统安徽部分,开了需求评审会,同时发现上个版本存在线上问题,进行了修复

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)
}