顺序更新返回结果之前和之后

时间:2018-12-12 03:00:19

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

我正在尝试使用Sequelize创建Update API路由,该路由将:

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

我的诺言链遇到了麻烦,诺言链在执行更新之前先执行了select查询之前和之后。我尝试了几种不同的方式来链接和捕获结果,但这是最新的代码:

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语句等待更新的最佳方法是什么?

在阐明如何链接承诺同时捕获结果的过程中提供的任何帮助将不胜感激!谢谢。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

试一下:

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

答案 2 :(得分:0)

尝试了多种方法后,终于可以与嵌套一起使用了

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()最后执行。另外,虽然我可以在promise链之外设置beforeRec,但是它对于afterRec无效。

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