javascript - 如何验证 Sequelize 交易并使其看起来不错

标签 javascript node.js validation transactions sequelize.js

在放下几年后,我正在尝试重新学习 NodeJS,因此我正在构建一个小型银行网站作为测试。我决定将 Sequelize 用于我的 ORM,但我在以我喜欢的方式在人与人之间汇款时遇到了一些麻烦。 这是我的第一次尝试:

// myUsername - who to take the money from
// sendUsername - who to send the money to
// money - amount of money to be sent from `myUsername`->`sendUsername`
// Transaction is created to keep a log of banking transactions for record-keeping.
module.exports = (myUsername, sendUsername, money, done) => {
    // Create transaction so that errors will roll back
    connection.transaction(t => {
        return Promise.all([
            User.increment('balance', {
                by: money,
                where: { username: myUsername },
                transaction: t
            }),
            User.increment('balance', {
                by: -money,
                where: { username: sendUsername },
                transaction: t
            }),
            Transaction.create({
                fromUser: myUsername,
                toUser: sendUsername,
                value: money
            }, { transaction: t })
        ]);
    }).then(result => {
        return done(null);
    }).catch(err => {
        return done(err);
    });
};

这行得通,但是它在递增时没有验证模型。当模型未验证时,我希望交易失败。我的下一次尝试是转到回调,如下所示(相同的函数头):

connection.transaction(t => {
        // Find the user to take money from
        return User
        .findOne({ where: { username: myUsername } }, { transaction: t })             .then(myUser => {
                    // Decrement money
                    return myUser
                    .decrement('balance', { by: money, transaction: t })
                    .then(myUser => {
                            // Reload model to validate data
                            return myUser.reload(myUser => {
                                    // Validate modified model
                                    return myUser.validate(() => {
                                            // Find user to give money to
                                            return User
                                            .findOne({ where: { username: sendUsername } }, { transaction: t })
                                            .then(sendUser => {
                                                    // Increment balance
                                                    return sendUser
                                                    .increment('balance', { by: money, transaction: t })
                                                    .then(sendUser => {
                                                            // Reload model
                                                            return sendUser.reload(sendUser => {
                                                                    // Validate model
                                                                    return sendUser.validate(() => {
                                                                            // Create a transaction for record-keeping
                                                                            return Transaction
                                                                            .create({
                                                                                    fromUser: myUser.id,
                                                                                    toUser: sendUser.id,
                                                                                    value: money
                                                                            }, { transaction: t });
                                                                    });
                                                            });
                                                    });
                                            });
                                    });
                            });
                    });
            });
    }).then(result => {
            return done(null);
    }).catch(err => {
            return done(err);
    });

这是有效的,因为钱仍然在人与人之间转移,但它仍然没有验证模型。我认为原因是 .validate().reload() 方法没有添加 transaction: t 的能力上的参数。 我的问题是是否有一种方法可以在交易中进行验证,但我也希望得到一些帮助来解决这个“回调 hell ”。同样,我已经有一段时间没有使用 JS 了,所以我现在才知道可能有更好的方法来做这件事。

谢谢!

最佳答案

我相信您无法在 Modelincrementdecrement 上触发验证,并且需要有实例。在某些 sequelize 模型方法中,您可以配置验证以运行,但它不会 look like it here

我会这样做

module.exports = async function(myUserId, sendUserId, money) {
  const transaction = await connection.transaction();
  try {
    const [myUser, sendUser] = await Promise.all([
      User.findById(myUserId, { transaction }),
      User.findById(sendUserId, { transaction })
    ]);
    await Promise.all([
      myUser.increment('balance', {
        by: money,
        transaction
      }),
      myUser.increment('balance', {
        by: -money,
        transaction
      })
    ]);
    await Transaction.create({...}, { transaction })
    await transaction.commit();
  } catch(e) {
    await transaction.rollback();
    throw e;
  }
}

关于javascript - 如何验证 Sequelize 交易并使其看起来不错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44826730/

相关文章:

javascript - 以编程方式确定要放置在图像上的最佳前景色

javascript - Dojo Widget 基础设施的 jQuery 答案

javascript - 从数组中删除在javascript中具有相同值的对象

javascript - 编写此 promise 链的更好方法

javascript - 如何将依赖项添加到我的 Spine 应用程序?

asp.net-mvc - database.SaveChanges()抛出EntityValidationException

javascript - 如何使用javascript验证动态生成的输入框值

ruby-on-rails - 验证消息助手或检索验证错误

javascript - 使用javascript从数组创建一个对象

c++ - Node-gyp 无法编译 nodejs 扩展 ('fatal error, thread' 找不到文件)