首页 > 解决方案 > Mysql 的 Javascript 异步行为

问题描述

我对 JS 的异步行为感到非常困惑。

我有一个 CSV 文件,其中包含需要抓取的 URL 列表。然后应该在 for 循环中将结果逐行添加到数据库中。

fs.readFile("./file.csv", async (err, data) => {
    if (err) {
      console.error(err);
      return;
    }
    let results = await neatCsv(data);
    db.connect();

    results.forEach(async row => {
      let ad = await kijiji.Ad.Get(row.url);
      let statement = "INSERT INTO Kijiji SET ?";

      let column = {
        uuid: uuid.v1(),
        url: ad.url,
        attributes: JSON.stringify(ad.attributes),
        latitude: ad.attributes.location.latitude,
        longitude: ad.attributes.location.longitude
      };
      const query = util.promisify(db.query).bind(db);
      await query(statement, column)
        .then()
        .catch(e => {
          throw e;
        });
    });

    const end = util.promisify(db.end).bind(db);
    await end()
      .then()
      .catch(e => {
        console.log(e);
        return failure({ status: e });
      });
});

这段代码的预期行为应该是同步的,因为根据我的理解,await kijiji.Ad.Get(row.url);并且await query(statement, column)表现得好像它是同步的,因为await使程序等待直到承诺被履行。

但是,我收到以下错误消息

错误:调用退出后无法将查询排入队列。becauseawait db.end()` 首先被调用。

我的主要问题是,在我的结果数组循环完成之前,如何在没有结束连接的情况下结束我的数据库连接?

更新:我将 forEach 转换为 for 循环,而我使用的是批量插入

fs.readFile("./src/file.csv", async (err, data) => {
  if (err) {
    console.error(err);
    return;
  }
  let results = await neatCsv(data);
  db.connect();
  values = [];
  for (let i = 0; i < results.length; i++) {
    let row = results[i];
    console.log(count);
    count++;
    let ad = await kijiji.Ad.Get(row.url);
    console.log(ad);
    let column = [
      uuid.v1(),
      ad.url,
      JSON.stringify(ad.attributes),
      ad.attributes.location.latitude,
      ad.attributes.location.longitude
    ];
    values.push(column);
  }
  let statement =
    "INSERT INTO Kijiji (uuid, url, attributes, latitude, longitude) SET ?";

  const query = util.promisify(db.query).bind(db);
  await query(statement, values)
    .then()
    .catch(e => {
      throw e;
    });
  db.end();
});

但是执行速度非常慢,每个 URL 大约需要 1-2 秒,而 foreach 大约需要几毫秒。为什么是这样?

标签: javascriptmysqlnode.jsweb-scrapingasync-await

解决方案


推荐阅读