如何异步使用array.map函数结合Sqlite3数据库更新数组每一项属性?
核心问题
sqlite3原生的db.get是回调风格的异步API,你没有将其包装为Promise返回,导致async映射函数没有等待查询完成就直接结束,返回值为undefined。你在db.get回调中写的return只作用于回调函数本身,不会被外层的async函数捕获。
其他可优化问题
- 你把
sqlite3引入、数据库实例创建逻辑放在了map循环内部,每遍历一条食品数据就会新建一次数据库连接,额外浪费大量资源 - 没有主动抛出查询错误,即使数据库查询失败也不会触发Promise.reject,不利于排查问题
- 直接用
require加载JSON文件会有缓存,如果你后续要重复执行这个函数更新数据,会拿到旧的JSON内容
修复后的代码
const fs = require('fs/promises'); const sqlite3 = require('sqlite3').verbose(); const { promisify } = require('util'); async function UpdateFoods(fileSource) { // 提前创建数据库连接,不要放在循环里 const db = new sqlite3.Database('/home/smichi/Coding/fdadata/fdadb.db'); // 把回调式的db.get包装成返回Promise的方法 const dbGet = promisify(db.get.bind(db)); // 用fs.readFile读JSON避免require缓存问题 const foodsRaw = await fs.readFile(fileSource, 'utf-8'); const foods = JSON.parse(foodsRaw); const ufoodsPromises = foods.map(async food => { const query = `SELECT fdc_id FROM food f WHERE description = ?`; try { const row = await dbGet(query, [food.Description]); return row ? {...food, fdc_id: row.fdc_id} : 1; } catch (err) { console.log('查询出错:', err); throw err; } }); const results = await Promise.all(ufoodsPromises); // 用完关闭数据库连接 db.close(); console.log(results); // 若需要把更新后的内容写回文件可取消注释下一行 // await fs.writeFile(fileSource, JSON.stringify(results, null, 2)) } UpdateFoods('../foodsdata/caffeine.json');
修改后Promise.all会等待所有数据库查询完成,再返回组装好的结果数组,不会再出现全undefined的情况。
内容的提问来源于stack exchange,提问作者Smichi
相关产品推荐
相关产品推荐

