You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何异步使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:06:04