找不到Bug:异步函数返回过快,批量插入SQL字符串缺失最后一页数据
问题原因
你的核心错误是使用了forEach执行异步回调:forEach原生不支持等待异步任务完成,你传入的async函数返回的Promise会被直接忽略,不会被等待。
while循环只会等待axios请求完成就继续执行,不会等当前页所有generateString的异步调用执行完毕,就进入下一轮循环/触发返回,所以bulkInsertString会漏掉还没拼接完成的SQL片段,你看到的最后一页打印晚于返回就是这个原因导致的。
修复代码
修改getBulkInsert函数内的逻辑即可,完整修改后的函数如下:
const getBulkInsert = async (schoolId, myDate) => { var bulkInsertString = ""; var lastPage = false; var endPoint = `***`; var i = 1; while (!lastPage) { console.log(`currently on element ${i} of response`); const config = { method: "get", url: endPoint, headers: { Authorization: "Bearer " + process.env.TOKEN, }, }; // 替换原来的.then写法,直接用await接收返回值 const response = await axios(config); const staffArray = response.data.data; console.log(`${staffArray.length} staff objects received in this API call`); lastPage = !response.data.meta.pagination.more; endPoint = response.data.meta.pagination.next; if (lastPage) { console.log("this is the final page"); } // 把forEach替换为map生成Promise数组,用Promise.all等待所有异步任务完成 const stringPromises = staffArray.map(async (staffMember) => { try { const { id, surname, forename, contact_details } = staffMember; const { data } = contact_details; const { emails } = data; const { primary, work } = emails; const getEmail = () => work ? work : primary; const nextString = await generateString("SyncStaff", "UpdatedAt", { StaffId: id, Surname: surname.replace(/'/g, '"'), FirstName: forename.replace(/'/g, '"'), StaffEmail: getEmail(), StaffRole: "Staff", UpdatedAt: myDate, }); console.log("string added", forename, surname); return nextString; } catch (err) { console.log(`error in staffMember ${staffMember.id}`, err); return ''; } }); // 等待当前页所有SQL片段生成完成再拼接 const pageStrings = await Promise.all(stringPromises); bulkInsertString += pageStrings.join(''); i += 1; } return bulkInsertString; };
注意事项
你当前直接拼接SQL字符串的写法存在SQL注入风险,建议后续改为参数化查询实现,避免数据异常导致SQL执行出错或者安全问题。
内容的提问来源于stack exchange,提问作者b.b.89
相关产品推荐
相关产品推荐

