2015-01-27 9 views
5

Desidero aggiornare un numero di tabelle del database in una singola transazione bookshelf. Potrei usare qualche aiuto per refactoring il mio codice. Sono nuovo al nodo e non ho una buona comprensione delle promesse, ma la struttura nidificata di seguito non è molto carina, e spero che ci sia un modo più pulito. Qualsiasi aiuto sarebbe apprezzato.Come risolvere la struttura nidificata nella transazione bookshelfjs

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

risposta

4

Salva le promesse-per-risultati a variabili e si possono utilizzare in seguito in finale allora dove è garantito che siano soddisfatte e quindi il loro valore può essere recuperato con .value() sincrono

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

Un altro modo è quello di utilizzare 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)); 
})}; 
+0

Molto meglio, t Hanks! –

+1

qual è il motivo dell'utilizzo del metodo call()? So che è una stenografia http://bluebirdjs.com/docs/api/call.html ma perché non chiamarla direttamente dal modello? – 1mike12

Problemi correlati