【问题标题】:Sequelize Update Returning Before and After Results在结果之前和之后返回 Sequelize 更新
【发布时间】:2019-05-13 02:38:31
【问题描述】:

我正在尝试使用 Sequelize 创建更新 API 路由:

  1. 捕获更新前的记录(beforeRec)
  2. 执行更新
  3. 捕获更新的记录 (updatedRec)
  4. 返回 beforeRec 和 updatedRec

我的 Promise 链出现问题,它在执行更新之前执行选择查询之前和之后。我尝试了几种不同的链接和捕获结果的方法,但这是最新的代码:

router.put('/:id', (req, res) => {
  const pk = req.params.id;

  const getBeforeRec = Master.findByPk(pk)
    .then(rec => {return rec})

  const updateRec = getBeforeRec
    .then(
      Master.update(
        req.body,
        { where: {id: pk} }
      )  
    )

  const getUpdatedRec = updateRec
    .then(
      Master.findByPk(pk)
        .then(rec => {return rec})
    );

  return Promise.all([getBeforeRec, updateRec, getUpdatedRec])
    .then( ([beforeRec, updateRes, afterRec]) => {
      return res.json({beforeRec, afterRec})
    })
    .catch(err => {
      return res.status(400).json({'error': err});
    });
});

下面是一个经过净化的结果示例:

{
    "beforeRec": {
        "id": 100,
        "updated_col_name": false,
    },
    "afterRec": {
        "id": 100,
        "updated_col_name": false,
    }
}

在控制台中,我可以看到更新是最后执行的:

Executing (default): SELECT [id], [updated_col_name] FROM [master] WHERE [master].[id] = N'100';
Executing (default): SELECT [id], [updated_col_name] FROM [master] WHERE [master].[id] = N'100';
Executing (default): UPDATE [master] SET [updated_col_name]=1 WHERE [id] = N'106'

让第二个 select 语句等待更新的最佳方法是什么?

任何帮助澄清如何在捕获结果的同时链接承诺将不胜感激!谢谢。

【问题讨论】:

    标签: javascript node.js promise sequelize.js es6-promise


    【解决方案1】:

    您可以使用更新查询返回的实例的 previous 方法来做到这一点:

    Master.update( req.body , { where: {id: pk} }).then(master => {
        console.log(master.get());          // <---- Will give you latest values
        console.log(master.previous());     // <---- returns the previous values for all values which have changed
    })  
    

    更多详情:

    http://docs.sequelizejs.com/class/lib/model.js~Model.html#instance-method-previous

    https://github.com/sequelize/sequelize/issues/1814

    【讨论】:

    • @AhmedGhrib,我在我的 2-3 个项目中使用过,master.previous() 会给你旧值,意味着更新前和master.get() 这会给你更新一次,我也给出了链接到文档,您可以阅读它。
    • @VivekDoshi 我也只得到更新的值。也许这个功能依赖于 DBMS
    【解决方案2】:

    尝试了很多方法,终于可以嵌套了:

    router.put('/:id', (req, res) => {
      const pk = req.params.id;
      let beforeRec;
    
      Master.findByPk(pk)
        .then(rec => { beforeRec = rec; })
        .then(() => {
          Master.update(
            req.body,
            { where: {id: pk} }
          )
          .then(() => {
            Master.findByPk(pk)
              .then(rec => { return rec; })
              .then((afterRec) => {
                return res.json({beforeRec, afterRec})
              })
          })
        })  
        .catch(err => {
          return res.status(400).json({'error': err});
        });
    });
    

    如果我不嵌套第二个 Master.findByPk,那么 Master.update() 最终会最后执行。此外,虽然我可以在承诺链之外设置 beforeRec,但它不适用于 afterRec。

    我不喜欢它,因为我仍然对承诺感到困惑,但它正在返回预期的结果。但是,由于这种嵌套混乱,我不确定 catch() 属于哪里。它会在嵌套的 then() 中捕获错误吗?只有进一步的测试才能证明。

    【讨论】:

      【解决方案3】:

      试一试:

      router.put('/:id', (req, res) => {
        const pk = req.params.id;
        let beforeRec, afterRec;
      
        Master.findByPk(pk)
          .then(rec => { beforeRec = rec; })
          .then(() => {
            Master.update(
              req.body,
              { where: {id: pk} }
            )
          })
          .then(() => {
            Master.findByPk(pk)
              .then(rec => { afterRec = rec; })
          })
          .then(() => {
            res.json({beforeRec, afterRec})
          })
          .catch(errror => {
            res.status(400).json({error});
          });
      });
      

      【讨论】:

      • 看起来应该可以,但是有两个问题: 1. afterRec 没有返回值;由于某种原因,它没有被设置 2. 更新仍在最后执行。我看到两个选择,然后更新。我找到了一个解决方案,我会在下面发布。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 2021-08-15
      • 2020-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多