Chrillewoodz
Chrillewoodz

Reputation: 28318

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: 795

Answers (1)

Chrillewoodz
Chrillewoodz

Reputation: 28318

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