Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the status of angular $interval - check if the interval has been cancelled or not

I am new to Angular (and JS) and just a little confused.

I start a timer with :

var getOverviewMapTimer = $interval($scope.UpdateOverviewMap, UPDATE_FREQUENCY); 

and, if I understand it, getOverviewMapTimer is a "promise".

I want to be able to check if the timer is running & had excepted that if I ever
$interval.cancel(getOverviewMapTimer); then getOverviewMapTimer would be null and I could check for that.

This seems not to be the case.

Do I have to explicitly destroy the promise (what goo is a promise to timer that has been cancelled?).? If so, how & would I then have to explicitly set it to null?

I think that I should use cancel(getOverviewMapTimer);, but am not 100% sure as getOverviewMapTimer is still non-null afterwards.

Thanks for your help

like image 229
Mawg says reinstate Monica Avatar asked Apr 18 '14 05:04

Mawg says reinstate Monica


3 Answers

After var getOverviewMapTimer = $interval(...); getOverviewMapTimer holds a reference to an object (that happens to be a promise).

Doing $interval.cancel(getOverviewMapTimer) passes (and cancels) the object referenced by the getOverviewMapTimer variable, but there is no way to convert an object to null. The getOverviewMapTimer variable will continue to hold a reference to the promise object and the only way to set it to null is through a new assignment (i.e. explicitely setting it to null):

var getOverviewMapTimer = $interval(...);
...
$interval.cancel(getOverviewMapTimer);
getOverviewMapTimer = null;

Advanced Topic:

It sounds indeed nice to have an easy way to find out if an interval-promise has been cancelled or not (e.g. adding a custom cancelled property to the promise object and setting its value to true when cancelling the interval).
Angular is cool enough to be incredibly flexible and extensible, so using the concept of a Service Decorator we are able to "augment" the $interval service, extending its cancel() method to add a cancelled property and setting its value to true when cancelling an interval-promise:

/* Service Decorators can be configured in `config` blocks */
app.config(function ($provide) {

    /* Register a decorator for the `$interval` service */
    $provide.decorator('$interval', function ($delegate) {

        /* Keep a reference to the original `cancel()` method */
        var originalCancel = $delegate.cancel;

        /* Define a new `cancel()` method */
        $delegate.cancel = function (intervalPromise) {

            /* First, call the original `cancel()` method */
            var retValue = originalCancel(intervalPromise);

            /* If the promise has been successfully cancelled,
             * add a `cancelled` property (with value `true`) */
            if (retValue && intervalPromise) {
                intervalPromise.cancelled = true;
            }

            /* Return the value returned by the original method */
            return retValue;
        };

        /* Return the original (but "augmented") service */
        return $delegate;
    });
});

Now, we can use the $interval service as usual and we can always check an interval-promise's cancelled property to find out if it has been cancelled.

var getOverviewMapTimer = $interval(...);
...
console.log(!!getOverviewMapTimer.cancelled);   // false
$interval.cancel(getOverviewMapTimer);
console.log(!!getOverviewMapTimer.cancelled);   // true

See, also, this short demo.

like image 192
gkalpak Avatar answered Nov 11 '22 23:11

gkalpak


It's technically impossible that getOverviewMapTimer is null after calling $interval.cancel(getOverviewMapTimer);.

If you want it to be null you have to do it yourself. Either immediately after cancelling the interval or via callback:

if ($interval.cancel(getOverviewMapTimer)) {
  getOverviewMapTimer = null;
}

or

var getOverviewMapTimer = $interval($scope.UpdateOverviewMap, UPDATE_FREQUENCY);
getOverviewMapTimer.catch(function() { getOverviewMapTimer = null; }); 

Be aware, though, that the callback is asynchronous.

like image 41
a better oliver Avatar answered Nov 11 '22 21:11

a better oliver


easy

var interval = $interval(function() { }, 1000);
console.log(interval.$$state.status); //0

$interval.cancel(interval);
console.log(interval.$$state.status); //2

if(interval.$$state.status == 0)
    //valid
else
    //invalid
like image 2
niskatqq Avatar answered Nov 11 '22 21:11

niskatqq