Brian
Brian

Reputation: 2305

AngularJS $timeout within a resource factory

I currently have an angular application which upon user login calls a service to begin a server call to refresh a count, only allowing for a server side return if the user is authenticated.

resource.approvalsCount = 0;
var approvalsCountTimer;
resource.getApprovalsCount = function (username) {
    return resource.query({
        username: username,
        q: 'approvalsCount'
    }).$then(function (response) {
        resource.approvalsCount = response.data.count;
        approvalsCountTimer = $timeout(resource.getApprovalsCount, 3000);
        return resource.approvalsCount;
    });
};

When a user logs out I am attempting to cancel that counter otherwise the server will return a 401 unauthorized error by calling a function based on the resource:

resource.cancelTimers = function () {
    $timeout.cancel(approvalsCountTimer);
}

The issue is that the counter continues to run even after I call the cancel upon the $timeout which returns a 401 from the server. Console logging out the return the cancel function returns true (cancel has worked). I have tried several different placements of the begin of the $timeout to no avail, is there a way to ensure that all of the $timeouts are canceled? I don't understand what I am missing in this configuration.

EDIT

angular.module('resources.approvals.approvals', ['ngResource'])
    .factory('Approvals', ['$timeout', '$resource', function ($timeout, $resource) {
    var resource = $resource('/approvals/:username/:requestID', {}, {
        'update': {
            method: 'PUT'
        }
    });
    resource.approvalsCount = 0;
    var approvalsCountTimer;
    resource.getApprovalsCount = function (username) {
        return resource.query({
            username: username,
            q: 'approvalsCount'
        }).$then(function (response) {
            resource.approvalsCount = response.data.count;
            approvalsCountTimer = $timeout(resource.getApprovalsCount, 3000);
            return resource.approvalsCount;
        });
    };
    resource.cancelTimers = function () {
        $timeout.cancel(approvalsCountTimer);
    };
    return resource;
}]);

Upvotes: 2

Views: 6494

Answers (1)

zs2020
zs2020

Reputation: 54524

I think your code looks good. It got to be something else.

I simplified a bit and you can see it on the demo. it simulates the http call every half second and the cancelTimes will be called in 4 seconds.

app = angular.module('app', []);
app.factory('Approvals', ['$timeout', function ($timeout) {
    var resource = {};
    resource.approvalsCount = 0;
    var approvalsCountTimer;
    resource.getApprovalsCount = function (username) {
        console.log(approvalsCountTimer);
        approvalsCountTimer = $timeout(resource.getApprovalsCount, 500);
    };
    resource.cancelTimers = function () {
        console.log("stopped");
        $timeout.cancel(approvalsCountTimer);
    };
    return resource;
}]);

function Ctrl($scope, $timeout, Approvals) {
    Approvals.getApprovalsCount();
    $timeout(Approvals.cancelTimers, 4000)
}

Upvotes: 1

Related Questions