Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

avoiding nested callbacks with promises

I'm still new to using Promise APIs and I'm struggling how to avoid deeply nested Promise chains, which as far as I understand, are one of the benefits to using Promises. Using the following pseudo code as an example, how do you avoid nesting Promises when the subsequent ones rely on the context of prior ones?

function loadDependency1() {
    // return a promsise to load the first dependency
}

function loadDependency2(dependency1) {
    // return a promise to load the second dependency, which relies on the first dependency
}

function loadDependency3(dependency2) {
    // return a promise to load the third dependency, which relies on the second dependency
}

function doWork(dependency1, dependency2, dependency3) {
    // finally have all the things necessary to do work
}

// load all the dependencies and eventually doWork
loadDependency1().then(function(dependency1) {
    return loadDependency2(dependency1).then(function(dependency2) {
        return loadDependency3(dependency2).then(function(dependency3) {
            doWork(dependency1, dependency2, dependency3);
        });
    });
});
like image 523
chinabuffet Avatar asked Jan 20 '14 19:01

chinabuffet


People also ask

How do you handle nested promises?

In a promise nesting when you return a promise inside a then method, and if the returned promise is already resolved/rejected, it will immediately call the subsequent then/catch method, if not it will wait. If promised is not return, it will execute parallelly.

Are promises better than callbacks?

They can handle multiple asynchronous operations easily and provide better error handling than callbacks and events. In other words also, we may say that, promises are the ideal choice for handling multiple callbacks at the same time, thus avoiding the undesired callback hell situation.

How do you use promises instead of callbacks?

Promises are JavaScript objects that represent an eventual completion or failure of an asynchronous operation. A promise is a returned object where you attach callbacks, instead of passing callbacks into a function. the place where you attach the callback after a successful completion of a task is called, . then().

Are promises just callbacks?

A promise represents the completion of an asynchronous function. It is an object that might return a value in the future. It accomplishes the same basic goal as a callback function, but with many additional features and a more readable syntax.


1 Answers

When you return a promise from then, it will resolve when that promise resolves:

So, if the next one only needs the previous one:

loadDependency1().then(function(dependency1) {
    return loadDependency2(dependency1);
}).then(function(dependency2) {
     return loadDependency3(dependency2);
}).then(function(dependency3) {
    doWork(dependency3);
});

Works if you need the third dependency.

If the dependencies are not dependent of each other:

Promise.all([loadDependency1(),loadDependency2(),loadDependency3])
.spread(function(dep1,dep2,dep3){
    doWork(dep1,dep2,dep3);
});

If you want to keep 'state' across the promise chain and are using a modern promise library such as Bluebird you can do:

loadDependency1().bind({}).then(function(dependency1) {
    this.dep1 = dependency1;
    return loadDependency2(dependency1);
}).then(function(dependency2) {
     this.dep2 = dependency2;
     return loadDependency3(dependency2);
}).then(function(dependency3) {
    doWork(this.dep1, this.dep2, dependency3);
});

If you're not (and you really should be :) ) You can .all you way around it:

loadDependency1().then(function(dependency1) {
    return [loadDependency2(dependency1),dependency1];
}).spread(function(dependency2,dep1) {
     return [loadDependency3(dependency2),dependency2,dep1];
}).spread(function(dependency3,dependency2,dependency1) {
    doWork(dependency1, dependency2, dependency3);
});
like image 93
Benjamin Gruenbaum Avatar answered Oct 12 '22 03:10

Benjamin Gruenbaum