Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluebird's Promise.all() method when one promise is dependent on another

I'm writing some code that currently looks like this because I have dependencies in my code. I was wondering if there was a cleaner way to do this with Promise.all()? Here is my pseudo code:

        return someService.getUsername()
            .then(function(username) {
                user = username;
            })
            .then(function() {
                return someService.getUserProps(user);
            })
            .then(function(userProps) {
                userProperties = userProps;
                return someService.getUserFriends(user);
            })
            .then(function(userFriends) {
                friends = userFriends;
            })
            .catch(error)
            .finally(function(){
                // do stuff with results
            });

The important thing is that I need user before I can make the second two calls for getUserProps() and getUserFriends(). I thought I could use Promise.all() for this like so:

var user = someService.getUsername()
    .then(function(username) {
        user = username;
    })
var getUserProps = someService.getUserProps(user);
var getUserProps = someService.getUserFriends(user);

return Promise.all(user, getUserProps, getUserFriends, function(user, props, friends) {
    // do stuff with results
})

But I cannot get this to work. Is this the correct case to use .all?

like image 953
Jeff Avatar asked Sep 17 '14 16:09

Jeff


2 Answers

Promise.all() is designed for parallel operation where you launch a bunch of async operations to run at the same time and then it tells you when they are all done.

It does not sequence one versus the completion of another in any way. So, you can't use it to wait for the user to be ready and then have the other operations use that user. It just isn't designed to do that.

You could get the user first and then when that is complete, you could use Promise.all() with your other two operations which I think can be run at the same time and don't depend upon each other.

var user;
someService.getUsername().then(function(username) {
    user = username;
    return Promise.all(getUserProps(user), getUserFriends(user));
}).then(function() {
    // do stuff with results array
}).catch(function() {
    // handle errors
});
like image 51
jfriend00 Avatar answered Sep 28 '22 09:09

jfriend00


You can use .all but you're going to have to make sure they run sequentially your code, you can do this by .thening them like you've done. If you do that you should use .join which is a shorthand for .all([...]).spread(....

var user = someService.getUsername();
var props = user.then(getUserProps)
var friends = user.then(getUserFriends)
Promise.join(user, props, friends, function(user, props, friends) {

    // everything is available here, everything is synchronized
});

If what you were trying to solve is the closure/nesting issue - then this is the way to do so.

like image 43
Benjamin Gruenbaum Avatar answered Sep 28 '22 10:09

Benjamin Gruenbaum