Using Q promises - is there a way to make this code less repetitive?
Q.ninvoke(mongoose,'connect', MONGODB_URL) .then(function () { console.log('Wiping database...'); return Q.ninvoke(mongoose.connection.db, 'dropDatabase'); }) .then(function () { console.log('Setting up test user...') return Q.ninvoke(User, 'createUser', { email: 'test@example.com', password: 'tester' }); }) .then(function (user) { console.log('Finished.'); process.exit(); }) .catch(function(err) { console.log(err); });
You can possibly shorten it with reusable oncomplete
helper like this:
function oncomplete(deferred) { return function (err, result) { if (err) deferred.reject(new Error(err)); else deferred.resolve(result); }}Q.fcall(function () { var deferred = Q.defer(); console.log('Connecting to database:', MONGODB_URL, '...'); mongoose.connect(MONGODB_URL, oncomplete(deferred)); return deferred.promise;}).then(function () { var deferred = Q.defer(); console.log('Wiping database...'); mongoose.connection.db.dropDatabase(oncomplete(deferred)); return deferred.promise;}).then(function () { var deferred = Q.defer(); console.log('Setting up test user...'); User.createUser({ email: 'test@example.com', password: 'tester' }, oncomplete(deferred)); return deferred.promise;}).done(function () { console.log('Finished.'); process.exit();}, function (err) { console.error('An error occurred:', err.stack);});
If you're brave enough, you can drastically simplify it with Node v0.11 beta and yield
keyword. That would implement an asynchronous state machine, so you could have pseudo-liner code flow without explicit callbacks.
Check out the async
module, specifically waterfall
. You can read about it here:
https://github.com/caolan/async#waterfalltasks-callback
Basically it allows you to chain a set of nested callbacks in a nice and concise manner.