Node.js sqlite3如何在db.each的所有异步回调完成后执行后续代码
解决方案
完全可以通过 Promise + Promise.all 实现需求,且不会触发全量查询结果加载到内存的问题,实现逻辑如下:
- 先声明空数组存储每一行异步处理逻辑对应的 Promise 实例
- 在
db.each的行处理回调中,将每行的异步操作返回的 Promise 存入数组 - 利用
db.each原生支持的 第三个参数(全量行遍历完成回调),在该回调内调用Promise.all等待所有异步操作执行完成,最后执行连接关闭逻辑
代码实现
const email = openEmailConnection(); // 存储所有行处理任务的Promise数组 const rowTaskPromises = []; db.each( "SELECT * FROM mytable", // 单条行数据处理回调 (err, row) => { if (err) throw err; // 包装异步处理逻辑为Promise存入数组 const singleRowTask = (async () => { const x = await makeNetworkApiCall(); await email.sendMail({message: "your message: " + x}); console.log("单条数据处理完成"); })(); rowTaskPromises.push(singleRowTask); }, // 所有行遍历完成的回调 async (err, totalCount) => { if (err) throw err; // 等待所有行的异步任务全部执行结束 await Promise.all(rowTaskPromises); // 执行收尾操作 await closeEmailConnection(); console.log(`共${totalCount}条数据全部处理完成,邮件连接已关闭`); } );
注意事项
- 如果需要避免单条数据处理失败导致所有任务中断,可以在每个
singleRowTask后追加catch单独捕获处理单条错误 - 该方案完全保留了
db.each逐行加载的特性,内存占用和原生使用db.each一致,不会出现全量数据载入内存的问题
内容的提问来源于stack exchange,提问作者Will Kanga
相关产品推荐
相关产品推荐

