Question

I'm building my first Angular app, and I've run into a problem. I have an AngularJS resource whose .get I call with both a success and error callback, like so:

var new_uptime = Uptime.get({}, function(){
    console.log("new_uptime", new_uptime, "$scope.uptime", $scope.uptime);
    console.log("new_uptime.uptime", new_uptime.uptime);
    if ($scope.uptime && new_uptime.uptime < $scope.uptime.uptime) {
        console.log("Reboot detected");
        location.reload(true);
    }
    $scope.uptime = new_uptime;
    $timeout(reload_uptime, 5000);
}, function(response){
    console.log("Failed to read uptime", response);
    console.log("Retrying in 10s");
    $scope.uptime = "[unknown]";
    $timeout(reload_uptime, 10000);
}); 

I've tested this with various error statuses from the server, and it works fine. Now I'd like to add app-wide retrying on 503s. I've added a module for that, which looks like this:

retry_module = angular.module('service.retry', []);
retry_module.factory("retry", ["$q", "$injector", "$timeout", function($q, $injector, $timeout) {
    return {
        "responseError": function(rejection) {
            console.log("Request failed", rejection);
            if (rejection.status != 503) {
                console.log("Unhandled status");
                return $q.reject(rejection);
            }
            var delay = Math.floor(Math.random() * 1000);
            console.log("Was 503, retrying in " + delay + "ms");
            var deferred = $q.defer();
            $timeout(function() {
                var $http = $http || $injector.get("$http");
                deferred.resolve($http(rejection.config));
            }, delay);
            return deferred;
        }
    };
}]);
retry_module.config(["$httpProvider", function ($httpProvider) {
    $httpProvider.interceptors.push("retry");
}]);

This works well for retrying on 503s, and successful attempts are handled by the success callback in the Uptime.get caller, as intended. However, if the server returns some other error, then I get the "Unhandled status" printout, but then neither "new_uptime" nor "Failed to read uptime". Where did my rejection go, and how do I go about trouble-shooting issues like this?

Was it helpful?

Solution

You need to return the promise, not the deferred. So the end of your responseError handler should be:

        var deferred = $q.defer();
        $timeout(function() {
            var $http = $http || $injector.get("$http");
            deferred.resolve($http(rejection.config));
        }, delay);
        return deferred.promise;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top