Search code examples
javascriptangularjspromisechainingangular-promise

AngularJS : How to flatten this Promise chain?


I have the following code:

someService.fnReturnsPromise()
    .then(function () {
        return someService.fnReturnsAnotherPromise(someArg);
    })
    .then(function (resultsOfSecondFn) {
        // do stuff with results
    });

I feel as if this should work; however, resultsOfSecondFn isn't actually the results, it's the promise itself that I returned. To make it work the way I want, I have to do this:

someService.fnReturnsPromise()
    .then(function () {
        return someService.fnReturnsAnotherPromise(someArg);
    })
    .then(function (promiseReturn) {
        promiseReturn.then(function (results) {
            // do stuff with results
        });
    });

This is the pseudo-code for fnReturnsAnotherPromise:

someService.fnReturnsAnotherPromise = function (arg1) {
    return anotherService.anotherFnThatReturnsPromise(arg1);
};

So really, it's just one extra layer, but a promise is getting returned either way. The code for anotherFnThatReturnsPromise is the simple paradigm of $q.defer(), return dfd.promise with some resolve()s.


Solution

  • Promises like Angular's are Promises/A+ compliant and are guaranteed to recursively assimilate promises. This is exactly to avoid nesting and simplify things like your case and is the point of promises.

    So even if you have a promise that returns and a promise that returns a promise you can unwrap it in a single .then call. For example:

    var p  = $q.when(1); // Promise<Int>
    var p2 = $q.when().then(function(){ return p;  }); // Promise<Promise<Int>>
    var p3 = $q.when().then(function(){ return p2; }); // Promise<Promise<Promise<Int>>>>
    p3.then(function(result) {
        console.log(result); // Logs 1, and Int and not p2's type
    });
    

    Or in your example:

    someService.fnReturnsPromise()
    .then(function() {
        return someService.fnReturnsAnotherPromise(someArg);
    })
    .then(function(resultsOfSecondFn) {
        // do work with results, it is already unwrapped
    });
    

    See this comparison with another language for perspective on promises not unwrapping.