获取数据在插入前执行

Getting data executes before insertion

我想先在循环中使用 Knex 在 MySQL 中插入数据,然后再获取数据。但是,在插入之前首先执行获取数据。 有人可以帮我做这件事吗?

for (let i = 0; i < fileArray.length; i++) {
  fileLocation = fileArray[i].location;
  imgLocationArray.push(fileLocation);
  knex("files")
    .insert({
      fileLink: fileLocation,
      todoId: todoId,
      userId: userId
    })
    .then(() => {
      console.log("phle chala!");
    })
    .catch(err => console.log(err));
}

knex("files")
  .where("files.userId", userId)
  .then(userFiles => {
    console.log("baad wala hai yrr");
    res.json({
      userFiles: userFiles
    });
  })
  .catch(err => console.log(err));

当使用承诺时(如 Knex 查询所做的那样)JavaScript 将直接继续下一条语句,而无需等待前一条语句完成。这就是您在这里遇到的情况:您的代码 开始 所有数据库插入,但在发出查询以取回数据之前不等待它们完成。

因为您要遍历一系列文件,Promise.all 是解决方案的理想候选者。这是它的工作原理。首先,我们收集所有的承诺:

const insertions = fileArray.map(file => {
  fileLocation = fileArray[i].location;
  imgLocationArray.push(fileLocation);
  return knex("files")
    .insert({
      fileLink: fileLocation,
      todoId: todoId,
      userId: userId
    })
})

请注意此处的 return 声明,这非常重要。接下来,我们等待所有这些承诺完成:

  Promise.all(insertions)
    .then(() => knex("files").where("files.userId", userId))
    .then(userFiles => {
      console.log("baad wala hai yrr");
      res.json({
        userFiles: userFiles
      });
    })
    .catch(err => console.log(err));

只有在最后的 .then 块中,我们才能依赖可用的数据,因为之前的所有查询都已完成。

如果您碰巧在服务器上的环境中工作,其中 async/await 可用(7.6 之后的 Node 版本),那么您可以这样做:

try {
  await Promise.all(insertions);
  const userFiles = await knex("files").where("files.userId", userId);
  res.json({ userFiles });
} catch (e) {
  // Handle database error
}

许多人发现此语法更具可读性。请注意,包含此代码的函数必须使用 async 关键字声明:

myExpressRouter.post("userfiles", async (req, res) => {
  // ...
})