Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

kriskowal/q node.js q.all and spread

I have a function that needs the result of three prior promises passed to it. One is linearly dependent and the other two can run concurrently. I want to use q.all to resolve the three promises, and then pass the results onto the fourth using .spread. My code however does not work. Any help would be appreciated.

var p1 = doWork(data);
var p2 = p1.then(doMoreWork);
var p3 = doConcurrentWork(data);

return q.all([p1,p2,p3]).spread(funcWith3params)
        .fail(function(err) {
            console.log(err):
        }

I can trace the code in node-inspector and see that the first 3 promises are being called. However, the function that .spread calls is not being called. Any clues as to why? Also .fail isn't being hit either.

like image 878
Daniel Byrne Avatar asked Jun 12 '13 05:06

Daniel Byrne


2 Answers

Spread calls q.all internally.

Here is the code for spread from q.js:

Q.spread = spread;
function spread(promise, fulfilled, rejected) {
    return when(promise, function (valuesOrPromises) {
        return all(valuesOrPromises).then(function (values) {
            return fulfilled.apply(void 0, values);
        }, rejected);
    }, rejected);
}

Note that it expects a promise that resolves to an array or an array as the first argument.

Therefore your call should look like this:

var p1 = doWork(data);
var p2 = p1.then(doMoreWork);
var p3 = doConcurrentWork(data);

return q.spread([p1,p2,p3], funcWith3params, function(err) {
        console.log(err):
    });

However, your original call should work as well. Not sure why it does not.

like image 51
Nathan Avatar answered Oct 12 '22 00:10

Nathan


The most succinct way to express the example you’ve provided is:

var p1 = doWork(data);
var p2 = p1.then(doMoreWork);
var p3 = doConcurrentWork(data);

return Q.spread([p1, p2, p3], funcWith3params)
    .done();

However, the original is correct as written.

I suspect that the problem is that one or more of the input promises is never resolving. Try using timeouts to isolate the problem.

var p1 = doWork(data).timeout(1000, 'p1 timed out');
var p2 = p1.then(doMoreWork).timeout(1000, 'p2 timed out');
var p3 = doConcurrentWork(data).timeout(1000, 'p3 timed out');

return Q.spread([p1, p2, p3], funcWith3params)
   .done();
like image 38
Kris Kowal Avatar answered Oct 12 '22 00:10

Kris Kowal