2015-01-27 10 views
5

Ich möchte eine Anzahl von Datenbanktabellen in einer einzigen Bookshelf-Transaktion aktualisieren. Ich könnte Hilfe bei der Refactoring meines Codes verwenden. Ich bin neu im Knoten und habe kein gutes Verständnis von Versprechen, aber die geschachtelte Struktur unten ist nicht sehr hübsch, und ich hoffe, dass es einen saubereren Weg gibt. Jede Hilfe wäre willkommen.Wie verschachtelte Struktur in Bookshelfjs-Transaktion zu beheben

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

Antwort

4

Speichern Sie die Versprechen-for-Ergebnisse zu Variablen und Sie können sie später im Finale verwenden dann, wo es garantiert ist, dass sie erfüllt sind und somit ihren Wert mit .value() synchron

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

abgerufen werden

Ein anderer Weg ist Promise.join zu verwenden:

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

Viel besser, t hanks! –

+1

Was ist der Grund für die Verwendung der Methode call()? Ich weiß, es ist eine Kurzschrift http://bluebirdjs.com/docs/api/call.html, aber warum nicht einfach direkt aus dem Modell anrufen? – 1mike12