3

I have a promise for an object and would like to get a promise for a property of that object. How should I do that?

var user = Q.nfcall(User.findOne, {
    _id: userId
});
var accessToken = Q.Promise(function (resolve, reject) {
    user.then(function (user) {
        if (!user) return reject(new Error('User not found.'));
        if (!user.github.accessToken) return reject(new Error('Access token not found.'));
        return resolve(user.github.accessToken);
    }, function(err) {
        return reject(err);
    });
});

This is what I tried so far, but I'm not sure if its the best (or most correct) way.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
mushroom
  • 1,909
  • 3
  • 16
  • 33

1 Answers1

7

Do not use the deferred antipattern1! There's no need to use Promise constructor, .then already returns you a promise for the result of its callback:

var accessToken = user.then(function(user) {
    if (!user) throw new Error('User not found.');
    if (!user.github.accessToken) throw new Error('Access token not found.');
    return user.github.accessToken;
});

[1]: You've seen yourself how errorprone it is :-)

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • If later accessToken is not "used" or "called", will user be called? – mushroom Apr 11 '15 at 11:46
  • @mushroom "promises" do not provide laziness. – zerkms Apr 11 '15 at 11:47
  • @mushroom `user` is a promise. It cannot be called. If you mean `User.findOne`, *you* already did call it via `Q.nfcall` explicitly to create the promise. – Bergi Apr 11 '15 at 11:47
  • 1
    @Bergi Ah yes, I was momentarily confused and should have thought more first. So `Q.nfcall()` immediately executes `User.findOne()` and returns a promise for `user`. It all makes sense now, thanks! – mushroom Apr 11 '15 at 11:49