W.P. McNeill
W.P. McNeill

Reputation: 17026

How to resolve a set of promises and values using Bluebird

I have a list values

xs = [1, 2, 3, 4]

I also have an asynchronous function square that returns a promise of the square of the argument passed to it. I want to pass the elements of my to list to my function in parallel, then collect the promises into an array and wait for them all to complete. I can formulate this as a map/reduce operation.

Promise
.map(xs, function(x) {
        return square(x)
    }
)
.reduce(function(ys, y) {
        return ys.concat(y)
    }, [])

This eventually returns the resolved values

[1, 4, 9, 16]

Easy enough. Now say I want to include the original argument in the answer array like so.

[{x:1, y:1}, {x:2, y:4}, {x:3, y:9}, {x:4, y:16}]

The tricky part is now I have a list of objects, each of which at the beginning of the reduce step has a promise buried in its y property. How do I write the Bluebird code to do this reduce step?

Upvotes: 4

Views: 1074

Answers (2)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276306

Here is how I'd write it, I'm using ES6 code through Babel in my bluebird.

import {props, map} from "bluebird";

map(xs, x => props({x, y:square(x)}); // do something with it :)

This uses Promise.props for waiting for properties of an object.

Upvotes: 3

Bergi
Bergi

Reputation: 664538

You wouldn't write this in the reduce step. Put it in the map step instead:

Promise.map(xs, function(x) {
    return f(x).then(function(y) {
        return {x:x, y:y};
    });
})

In fact, you wouldn't have any reduce step at all, because map does already collect the results in an array.

Of course, you could split this in two and flatten your code by doing

Promise.map(xs, f).map(function(y, i) {
    return {x:xs[i], y:y};
})

but I don't think that xs[i] thing is much better.

Upvotes: 5

Related Questions