Chrillewoodz
Chrillewoodz

Reputation: 28368

Cancelling $timeout doesn't work

Performing the simple task of cancelling a $timeout doesn't work. I've got a status box containing messages to the user so if a new message is set before the timeout has run out then I need to restart the timeout by cancelling it and restarting it.

I've looked at the docs and other answers on this site but I don't seem to be doing anything different.

I get no errors. What am I doing wrong?

The service:

core.service('statusHandler', ['$timeout', function($timeout) {

    var status = {
        message: '',
        isSuccess: false,
        isActive: false,
        isBoxDirective: false,
        timeout: null
    };

    this.resetStatus = function() {
        status.isSuccess = false;
        status.isActive = false;
        status.isBoxDirective = false;

        $timeout.cancel(status.timeout);
    };

    this.setStatus = function(message, isSuccess, isBoxDirective) {

        status.message = message || 'Something went wrong';
        status.isSuccess = isSuccess;
        status.isActive = true;
        status.isBoxDirective = isBoxDirective;

        status.timeout = $timeout(function() {
            status.isActive = false;
        }, 5000);
    };

    this.getStatus = function() {
        return status;
    };
}]);

Then I use it in a directive like this:

core.directive('statusBox', ['statusHandler', function(statusHandler) {

    return {
        scope: {},
        controller: 'MainCtrl',
        controllerAs: 'core',
        templateUrl: '/app/views/components/core/status-box.html',
        link: function(scope, element, attrs, ctrl) {

            scope.$watch(function() {
                return statusHandler.getStatus();
            }, function(newVal, oldVal) {
                ctrl.status = newVal;
            }, true);
        }
    };
}]);

Calling the resetStatus() from a controller like this:

...

var completed;

... some logic to set completed to true ...

$scope.$watch(function() {
    return completed;
}, function(newVal) {

    if (completed) {

        statusHandler.resetStatus();
        statusHandler.setStatus('Videos have finished uploading and are now being processed', true, false);
    }
});

...

Upvotes: 0

Views: 796

Answers (1)

Chrillewoodz
Chrillewoodz

Reputation: 28368

Managed to solve it by just clearing the previous timeout before assigning a new timeout within the same function at the start. Which does the trick!

It appeared to be some sort of function scope issue as calling the function from resetStatus() did nothing.

this.setStatus = function(message, isSuccess, isBoxDirective) {

    $timeout.cancel(status.timeout);

    status.message = message || 'Something went wrong';
    status.isSuccess = isSuccess;
    status.isActive = true;
    status.isBoxDirective = isBoxDirective;

    status.timeout = $timeout(function() {
        status.isActive = false;
    }, 5000);
};

Upvotes: 2

Related Questions