0

I have a function that is using promises and the Q library, essentially I want to wait until all the promises have compelted before returning, but my code is just falling through:

function makeSomething(){

        var something = new Something()

    Q.all([

        somethingPromise1(something)
        , somethingPromise2(something)

    ]).spread(function(resultsFromP1, resultsFromP2){

        something.otherValue =  resultsFromP2

    }).done()

    return something
}

var something = makeSomething()
console.log(something.otherValue)

The code is more complicated, but this is the gist. Calling it is more along the lines of

something = _.find(things, function(){})
if(!something ) something  = makeSomething()

then

manyMoreInterestingTasks(something)

I don't want my calling code to have to fork on an if. Essentially I want makeSomething too block until it returns. I am new to Node and Q so I apologize if I am abusing the approach...

akaphenom
  • 6,728
  • 10
  • 59
  • 109

1 Answers1

1

Essentially I want makeSomething too block until it returns.

It's impossible to get the result from the Promise synchronously. The othervalue property is created asynchronously, but you're returning something immediately. Better:

function makeSomething(){
    return Q.all([
        somethingPromise1(something),
        somethingPromise2(something)
    ]).spread(function(resultsFromP1, resultsFromP2){
        var something = new Something(resultsFromP1);
        something.otherValue = resultsFromP2;
        return something;
    });
}

You need to put your whole code in promises! However, that is not as complicated as it sounds:

// Quite narrative actually (the "then" even was in you question already :-) ):
Q(_.find(things,function(){}) || makeSomething()).then(manyMoreInterestingTasks);

// More verbose version of above:
var something = _.find(things, function(){});
var promiseForSomething = something ? Q(something) : makeSomething();
promiseForSomething.then(function(something) {
    manyMoreInterestingTasks(something);
});

// Similar thing within the chain:
Q( _.find(things, function(){}) ).then(function(something) {
    // returning either a promise or a plain value from the callback
    if (!something)
        return makeSomething();
    else
        return something;
}).then(manyMoreInterestingTasks);

// With explicit error propagation and recovery:
function findSomething() {
    var something = _.find(things, function(){});
    if (something)
        return Q(something);
    else
        return Q.reject("couldn't find anything");
}
findSomething().catch(makeSomething).then(manyMoreInterestingTasks);
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • How would i handle the "Use this if it is OK" or "This one if not" logic in a promise? – akaphenom Feb 26 '14 at 20:58
  • interesting. I would not have considered that approach – akaphenom Feb 26 '14 at 21:00
  • You can explicitly fail (`throw`) when it is not OK, and then recover with [`.catch(makeSomething)`](https://github.com/kriskowal/q#handling-errors). Or you put the condition in the `then` callback, from which you either return a promise for the `something` or the promise from `makeSomething()` - the next function in the chain would use it then. In the example above, I've simplified the condition and used [the `Q` function](https://github.com/kriskowal/q/wiki/API-Reference#wiki-qvalue) for the chain start. – Bergi Feb 26 '14 at 21:04
  • 1
    Alternatively, if it is "safe" to use the rest of the `Something` object, you could assign the promise to the `otherValue` field and still return the created `Something`. Then any processes which need `otherValue` would `.then` on that promise and parts which didn't need the `otherValue` would not wait. However, returning an object with "real" values and promises at the same time is probably not considered a "Best Practice". – squid314 Feb 26 '14 at 21:05
  • Thank you. This answer is all kinds of awesome and enlightening to me. I think it just "clicked", but I can't promise (pun intended) that I won't be back for more help soon. Thank you – akaphenom Feb 27 '14 at 13:18