【问题标题】:How to fix nested structure in bookshelfjs transaction [duplicate]如何修复bookshelfjs事务中的嵌套结构[重复]
【发布时间】:2015-01-27 17:16:24
【问题描述】:

我想在单个书架事务中更新多个数据库表。我可以使用一些帮助来重构我的代码。我是node新手,对promise没有很好的理解,但是下面的嵌套结构不是很漂亮,我希望有一个更干净的方法。任何帮助将不胜感激。

function insertUser(user, cb) {
  bookshelf.transaction(function(t) {
  var key = user.key;
  Developer.forge({key: key})
  .fetch({require: true, transacting: t})
  .then(function(developerModel) {
    var devID = developerModel.get('id');
    Address.forge(user.address)
    .save(null, {transacting: t})
    .then(function(addressModel) {
      var addressID = addressModel.get('addressId');
      Financial.forge(user.financial)
      .save(null, {transacting: t})
      .then(function(financialModel) {
        var financialID = financialModel.get('financialId');
        var userEntity = user.personal;
        userEntity.addressId = addressID;
        userEntity.developerId = devID;
        userEntity.financialId = financialId;
        User.forge(userEntity)
        .save(null, {transacting: t})
        .then(function(userModel) {
          logger.info('saved user: ', userModel);
          logger.info('commiting transaction');
          t.commit(userModel);
        })
        .catch(function(err) {
          logger.error('Error saving user: ', err);
          t.rollback(err);
        });
      })
      .catch(function(err) {
        logger.error('Error saving financial data: ', err);
        t.rollback(err);
      })
    })
    .catch(function(err) {
      logger.error('Error saving address: ', err);
      t.rollback(err);
    })
  })
  .catch(function(err) {
    logger.error('Error saving business : ', err);
    t.rollback(err);
  })
})
.then(function(model) {
  logger.info(model, ' successfully saved');
  return Promise.resolve(respond.success({userId: model.get('userId')}));
})
.catch(function(err) {
  logger.error(err, ' occurred');
  return Promise.reject(new DatabaseError('Unable to write user to database due to error ', err.message));
})};

【问题讨论】:

    标签: javascript node.js promise bookshelf.js


    【解决方案1】:

    将 promises-for-results 保存到变量中,您可以稍后在 final 中使用它们,然后保证它们得到满足,因此可以使用 .value() 同步检索它们的值

    function insertUser(user, cb) {
      return bookshelf.transaction(function(t) {
        var key = user.key;
    
        var devID = Developer.forge({key: key})
          .fetch({require: true, transacting: t})
          .call("get", "id");
    
        var addressID = devID.then(function() {
          return Address.forge(user.address).fetch({require: true, transacting: t})
        }).call("get", "addressId");
    
        var financialID = addressModel.then(function() {
          return Financial.forge(user.financial).save(null, {transacting: t})
        }).call("get", "financialId");
    
        var userModel = financialID.then(function() {
          var userEntity = user.personal;
          userEntity.addressId = addressID.value();
          userEntity.developerId = devID.value();
          userEntity.financialId = financialID.value();
          return User.forge(userEntity).save(null, {transacting: t});
        });
    
        return userModel.then(function(userModel) {
          logger.info('saved user: ', userModel);
          logger.info('commiting transaction');
          t.commit(userModel);
        }).catch(function(e) {
          t.rollback(e);
          throw e;
        });
      });
    }
    .then(function(model) {
      logger.info(model, ' successfully saved');
      return Promise.resolve(respond.success({userId: model.get('userId')}));
    })
    .catch(function(err) {
      logger.error(err, ' occurred');
      return Promise.reject(new DatabaseError('Unable to write user to database due to error ', err.message));
    })};
    

    另一种方式是使用Promise.join

    function insertUser(user, cb) {
      return bookshelf.transaction(function(t) {
        var key = user.key;
    
        var devID = Developer.forge({key: key})
          .fetch({require: true, transacting: t})
          .call("get", "id");
    
        var addressID = devID.then(function() {
          return Address.forge(user.address).fetch({require: true, transacting: t})
        }).call("get", "addressId");
    
        var financialID = addressModel.then(function() {
          return Financial.forge(user.financial).save(null, {transacting: t})
        }).call("get", "financialId");
    
        var userModel = Promise.join(devID, addressID, financialID,
         function(devID, addressID, financialID) {
          var userEntity = user.personal;
          userEntity.addressId = addressID;
          userEntity.developerId = devID;
          userEntity.financialId = financialID;
          return User.forge(userEntity).save(null, {transacting: t});
        });
    
        return userModel.then(function(userModel) {
          logger.info('saved user: ', userModel);
          logger.info('commiting transaction');
          t.commit(userModel);
        }).catch(function(e) {
          t.rollback(e);
          throw e;
        });
      });
    }
    .then(function(model) {
      logger.info(model, ' successfully saved');
      return Promise.resolve(respond.success({userId: model.get('userId')}));
    })
    .catch(function(err) {
      logger.error(err, ' occurred');
      return Promise.reject(new DatabaseError('Unable to write user to database due to error ', err.message));
    })};
    

    【讨论】:

    • 好多了,谢谢!
    • 使用 call() 方法的原因是什么?我知道它是简写 bluebirdjs.com/docs/api/call.html 但为什么不直接从模型中调用它呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 2012-09-14
    • 1970-01-01
    • 2016-04-09
    • 2021-09-01
    相关资源
    最近更新 更多