Can you resolve an angularjs promise before you return it?

Craig Celeste picture Craig Celeste · Dec 12, 2013 · Viewed 87.6k times · Source

I am trying to write a function that returns a promise. But there are times when the information requested is available immediately. I want to wrap it in a promise so that the consumer doesn't need to make a decision.

function getSomething(id) {
    if (Cache[id]) {
        var deferred = $q.defer();
        deferred.resolve(Cache[id]); // <-- Can I do this?
        return deferred.promise;
    } else {
        return $http.get('/someUrl', {id:id});
    }
}

And use it like this:

somethingService.getSomething(5).then(function(thing) {
    alert(thing);
});

The problem is that the callback does not execute for the pre-resolved promise. Is this a legitimate thing to do? Is there a better way to handle this situation?

Answer

h.coates picture h.coates · Jan 20, 2014

Short answer: Yes, you can resolve an AngularJS promise before you return it, and it will behave as you'd expect.

From JB Nizet's Plunkr but refactored to work within the context of what was originally asked (i.e. a function call to service) and actually on site.

Inside the service...

function getSomething(id) {
    // There will always be a promise so always declare it.
    var deferred = $q.defer();
    if (Cache[id]) {
        // Resolve the deferred $q object before returning the promise
        deferred.resolve(Cache[id]); 
        return deferred.promise;
    } 
    // else- not in cache 
    $http.get('/someUrl', {id:id}).success(function(data){
        // Store your data or what ever.... 
        // Then resolve
        deferred.resolve(data);               
    }).error(function(data, status, headers, config) {
        deferred.reject("Error: request returned status " + status); 
    });
    return deferred.promise;

}

Inside the controller....

somethingService.getSomething(5).then(    
    function(thing) {     // On success
        alert(thing);
    },
    function(message) {   // On failure
        alert(message);
    }
);

I hope it helps someone. I didn't find the other answers very clear.