【问题标题】:How can I make the commit wait until the if statement has ran?如何让提交等到 if 语句运行?
【发布时间】:2020-01-13 07:48:55
【问题描述】:

该函数使用 mysql2 和 promise 包装器进行事务。 对于每个任务,可以有多个链接,格式为 JSON。

对于每个链接,我需要在插入任务后插入数据库。但是,如果 JSON 错误(请参阅下面的“no”而不是“name”),则需要抛出错误并且永远不会发生提交。

{
    "title": "Test new from POSTMAN many link",
    "header": "POSTMAN test many links",
    "category": "POSTMAN test many links",
    "notes": "Task created from POSTMAN many link",
    "links": [{"name": "Lenovo", "link": "https://www.lenovo.com"}, {"no": "Microsoft", "link": "https://www.microsoft.com"}],
    "level": 2 
}

我已经尝试过嵌套的 try/catch 块,但这不会在它下面的提交之前运行

await conn.beginTransaction();
        const [task] = await conn.query("INSERT INTO tasks SET ? ", [taskObj]);
        if (req.body.links.length > 0) {
            req.body.links.map(async e => {
                try {
                    const link = {
                        task_id: task.insertId,
                        name: e.name,
                        link: e.link
                    };
                    await conn.query("INSERT INTO links SET ? ", [link]);
                } catch (err) {
                    console.log(err);
                    conn.rollback();
                    conn.release();
                }
            });
        }

        // this runs before my if statement above
        console.log("about to commit");
        await conn.commit();
        conn.release();
        return res.send({ data: taskObj, message: "Task created" });
    } catch (e) {
        conn.rollback();
        conn.release();
        console.log(e);
        return res.send({ message: "error" });
    }

如果任务插入失败或链接插入失败,我希望错误确保不会发生提交。

【问题讨论】:

  • 只是一个建议,寻找knexjs.org它有简单的API,事务可以像这样运行await dbConnection(async transaction => {... do your async task inside transaction. Throw error if something didn't work out and transaction would be rolled back})

标签: mysql node.js async-await


【解决方案1】:

参见示例:

(async () => {
  try {
    await conn.beginTransaction();
    const [task] = await conn.query("INSERT INTO tasks SET ? ", [taskObj]);
    if (req.body.links.length > 0) {
      const promises = req.body.links.map(async e => {
        const link = {
          task_id: task.insertId,
          name: e.name,
          link: e.link
        };
        await conn.query("INSERT INTO links SET ? ", [link]);
      });
      await Promise.all(promises);
    }

    // this runs before my if statement above
    console.log("about to commit");
    await conn.commit();
    conn.release();
    return res.send({ data: taskObj, message: "Task created" });
  } catch (e) {
    await conn.rollback();
    await conn.release();
    console.log(e);
    return res.send({ message: "error" });
  }
})();

【讨论】:

  • 完美!谢谢你。为了澄清我的理解,promises 是一个存储对所有 conn.query 的引用然后执行它们的变量吗?
  • 变量promises 存储使用map 函数创建的Promise 对象。 Promise.all() 方法返回一个 Promise,当所有作为 iterable 传递的 Promise 都已解决或 iterable 不包含任何 Promise 时,该 Promise 将解决。见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
猜你喜欢
  • 2017-12-22
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
相关资源
最近更新 更多