简体   繁体   English

Sequelize 更新返回前后结果

[英]Sequelize Update Returning Before and After Results

I'm trying to create an Update API route using Sequelize that will:我正在尝试使用 Sequelize 创建一个 Update API 路由,它将:

  1. Capture the record before the update (beforeRec)捕获更新前的记录(beforeRec)
  2. Perform the update执行更新
  3. Capture the updated record (updatedRec)捕获更新记录(updatedRec)
  4. Return both the beforeRec and updatedRec返回 beforeRec 和 updatedRec

I'm having trouble with my promise chain, which is executing the before and after select queries before executing the update.我的承诺链有问题,它在执行更新之前执行之前和之后的选择查询。 I've tried several different ways of chaining and capturing results, but here's the latest code:我尝试了几种不同的链接和捕获结果的方法,但这是最新的代码:

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});
    });
});

Here's a sanitized example of how the results look:下面是结果外观的净化示例:

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

In the console, I can see that the update is executing last:在控制台中,我可以看到更新是最后执行的:

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'

What's the best way to make the second select statement wait for the update?让第二个选择语句等待更新的最佳方法是什么?

Any help in clarifying how to chain promises while capturing results along the way will be greatly appreciated.任何有助于阐明如何在沿途捕获结果的同时链接承诺的任何帮助将不胜感激。 Thanks.谢谢。

You can do that with , previous method of the instance that returned by update query : 您可以使用update查询返回的实例的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
})  

For More Detail : 有关更多详细信息:

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

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

Give this a shot: 试一下:

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});
    });
});

After trying a number of ways, it finally works with nesting: 在尝试了多种方法之后,它最终可以与嵌套一起使用:

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});
    });
});

If I don't nest the second Master.findByPk, then Master.update() ends up executing last. 如果我不嵌套第二个Master.findByPk,则Master.update()最后执行。 Also, while I can set beforeRec outside of the promise chain, it didn't work for afterRec. 另外,虽然我可以在promise链之外设置beforeRec,但是它对于afterRec无效。

I don't love it, since I'm still confused by promises, but it's returning the desired results. 我不喜欢它,因为我仍然对诺言感到困惑,但是它正在返回期望的结果。 However, with this nesting mess, I'm not sure where the catch() belongs. 但是,由于这种嵌套混乱,我不确定catch()属于哪里。 Will it catch errors within the nested then()s? 它会在嵌套的then()中捕获错误吗? Only further testing will tell. 只有进一步的测试才能证明。

Resurrecting an old question to help people in the future...复活一个老问题来帮助未来的人......

I've been using sequelize v6 with MySQL.我一直在使用 sequelize v6 和 MySQL。 I can't speak to other variances but assuming you just want the snapshot of the "previous" values, you can use the following method to create a copy the properties and their values before updating them我不能说其他差异,但假设您只想要“先前”值的快照,您可以使用以下方法在更新属性及其值之前创建一个副本

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

  let beforeRecord;
  const updateRec = Master.findByPk(pk).then(rec => {
    // .get() method is synchronous
    beforeRecord = rec.get({ plain: true });
    // calling .update on the model instance will also
    // call .reload on the instance as well.
    // Same thing happens when calling .save on the instance
    return rec.update(req.body);
  });

  updateRec.then(rec => {
    const afterRec = rec.get({ plain: true });
    return res.json({beforeRec, afterRec})
  }).catch(err => {
    return res.status(400).json({'error': err});
  });

});
// Async await method
router.put('/:id', async (req, res) => {
  const pk = req.params.id;

  try {
    /** @type{import('sequelize').Model} */ // rec equals a sequelize model instance
    const rec = await Master.findByPk(pk)
    // .get() method is synchronous and returns an object (NOT a sequelize model instance)
    const beforeRecord = rec.get({ plain: true });
    // calling .update on the model instance will also
    // call .reload on the instance as well.
    // Same thing happens when calling .save on the instance
    await rec.update(req.body); // after this call, rec contains the new updated values

    const afterRec = rec.get({ plain: true });
    return res.json({beforeRec, afterRec})
  } catch (err) {
    return res.status(400).json({'error': err});
  }

});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM