如何合理高效扩展考勤查询功能避免重复代码及TypeError报错
问题原因
你遇到的TypeError: Cannot set property 'lazy_count' of undefined报错是重复复制异步查询代码块导致的:每新增一个员工你就新增了4个嵌套的数据库异步请求,大量并发异步请求会篡改数据库驱动的内部状态,再加上全局变量命名冲突,就会触发属性赋值异常。
另外你的原有实现查询次数和员工数量成正比,10个员工就要执行40次数据库查询,性能损耗非常大。
优化方案
可以通过批量查询+逻辑复用的方式解决,一共只需要3次数据库查询就能覆盖所有员工的考勤统计,新增员工不需要再复制代码,只需要在配置数组里添加对应信息即可。
优化后代码如下:
// 员工配置项,新增员工直接在此处按格式添加即可 const staffList = [ { opid: 6, name: 'George' }, { opid: 3, name: 'Dave' }, // 其余8名员工按 {opid: 对应OPID, name: '员工姓名'} 格式补充 ] // 批量查询所有员工的最新考勤记录 db.query(`SELECT a.* FROM ATTENDEVENTS a INNER JOIN ( SELECT OPID, MAX(DATETIME) as max_time FROM ATTENDEVENTS WHERE OPID IN (${staffList.map(item => item.opid).join(',')}) GROUP BY OPID ) b ON a.OPID = b.OPID AND a.DATETIME = b.max_time`, function(err, latestAttendRows) { if (err) throw err // 构造考勤记录映射表,方便快速匹配对应员工的考勤数据 const attendMap = {} latestAttendRows.forEach(row => attendMap[row.OPID] = row) // 批量查询所有员工的基础信息 db.query(`SELECT opid, name FROM OPS WHERE OPID IN (${staffList.map(item => item.opid).join(',')})`, function(err, staffRows) { if (err) throw err const staffMap = {} staffRows.forEach(row => staffMap[row.OPID] = row) // 全局查询最新的ATTENDEVENTID,只需要查1次 db.query('SELECT FIRST 1 ATTENDEVENTID FROM ATTENDEVENTS ORDER BY DATETIME DESC', function(err, lastIdRow) { if (err) throw err const lastID = lastIdRow.length === 1 ? lastIdRow[0].ATTENDEVENTID : 0 // 遍历所有员工输出状态,无需重复写逻辑 staffList.forEach(staff => { const currentAttend = attendMap[staff.opid] const clockedIn = currentAttend && currentAttend.EVENTTYPE === 0 // 保留原有错误校验逻辑 if (!staffMap[staff.opid]) { console.log(`error 1: 员工${staff.name}基础信息不存在`) return } if (!clockedIn && currentAttend?.EVENTTYPE === 0) { console.log(`error 2: 员工${staff.name}考勤状态异常`) return } // 输出考勤状态 console.log(clockedIn ? `${staff.name} is clocked in` : `${staff.name} is not clocked in`) }) }) }) })
内容的提问来源于stack exchange,提问作者daneee
相关产品推荐
相关产品推荐

