Skip to content

Instantly share code, notes, and snippets.

@JamesMGreene
Created November 24, 2012 15:47
Show Gist options
  • Save JamesMGreene/4140215 to your computer and use it in GitHub Desktop.
Save JamesMGreene/4140215 to your computer and use it in GitHub Desktop.
Using Q, is this the best way to pass the results of two sequenced promises to the subsequent `then`/`spread` clause?
'use strict';
var Q = require('q');
var cmd = new require('commander').Command();
var client = new require('myAwesomeApi').Client();
var getUsername = function(done) {
var username;
cmd.prompt('Username: ', function(name) {
if (!name) {
done(new Error('You must provide a username!'));
}
else {
done(null, username);
}
});
};
var getPassword = function(done) {
cmd.password('Password: ', '*', function(pass) {
if (!pass) {
done(new Error('You must provide a password!'));
}
else {
process.stdin.destroy();
done(null, pass);
}
});
};
Q.napply(getUsername, null, []).then(function(username) {
return Q.napply(getPassword, null, []).then(function(password) {
return Q.resolve([username, password]);
});
}).spread(function(username, password) {
return Q.napply(client.login, client, [username, password]);
})
@JamesMGreene
Copy link
Author

@domenic:
Thanks, I grabbed 0.8.11 and updated all of my nbind calls to nfbinds. However, I am curious about the done method: if I have a fail handler in my promise chain, does it need to come before the done handler? Previously, my promise chain ended as .then(...).fail(...).end(); but I get the impression that it now needs to end as .fail(...).done(...);. Correct?

I assume I could still have it structured as before but just replace end with done (so .then(...).fail(...).done(); but it sounds like that would actually be a slightly sub-optimal setup due to the extra then hiding inside of then that would be used superfluously... right?

@JamesMGreene
Copy link
Author

FWIW, using .fail(...).done(...); feels very unnatural to me as the done handler is receiving a resolved promise value from my previous then but the fail handler is in the middle of the two, creating a mentally diverted/disjoint flow. Recommendations to fix that?

Where do you normally put your fail handler? Or, do you instead use the done handler's rejection argument (2nd function)? Would the done handler's rejection function receive failures from any point in the promise chain like fail does? I'm guessing not.

@domenic
Copy link

domenic commented Nov 26, 2012

No, fail shouldn't go before done; in that case: it does change the semantics.

.then(f1, r1, p1).fail(f2).end() should be replaced with .then(f1, r1, p1).fail(f2).done() or .then(f1, r2, p1).done(undefined, f2). I often cap with an empty .done(); I sometimes use .done(f) or sometimes .done(f, r).

Also: if you're writing only for Node you can use .catch instead of .fail (and .finally instead of .fin).

@JamesMGreene
Copy link
Author

Cool, I'll go with catch (definitely prefer its obviously semantic name over fail) and an empty done. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment