1

Following is what I'm trying to do. When the first timeout is forcibly cancelled, I want to initiate the second timeout function, without the lag that already exists, had the timeout not been cancelled.

$scope.data1_timeout = $timeout(function() {
  // some action
}, 2000);

$scope.data2_timeout = $timeout(function() {
  // some action
}, 4000);

$scope.show = function() {
  if (some action) {
    $timeout.cancel($scope.data1_timeout); //works perfectly fine
    //But how do I update data2_timeout so that the action inside it occurs just after data1_timeout is cancelled in this block.
  }
}
lin
  • 17,956
  • 4
  • 59
  • 83
Siena
  • 778
  • 10
  • 23

2 Answers2

1

Easy doing by cancel both $timeout's and call your function manually. Keep it simple =).

$scope.data1_timeout = $timeout(function() {
  // some action
}, 2000);

$scope.data2_timeout = $timeout(function() {
  myAction();
}, 4000);

$scope.show = function() {
  if (some action) {
    $timeout.cancel($scope.data1_timeout);
    $timeout.cancel($scope.data2_timeout);
    myAction();
  }
}

function myAction () {
  console.log('done');
}
lin
  • 17,956
  • 4
  • 59
  • 83
  • Better yet, why not declare `myAction` at the top and make it the 2nd timer's callback? – tavnab Aug 28 '17 at 16:33
  • @tavnab 1) No need to declare on top. This doesn't make sense at all. 2) Timers don't have a callback, `$timeout`'s uses `promises`. Please read the doc -> https://docs.angularjs.org/api/ng/service/$timeout. – lin Aug 28 '17 at 16:35
  • 1
    1) It's clearer to declare it at the top for readability, so you know what you're calling. 2) I'm sorry if I wan't clear. What I meant was that you can just do `$scope.data2_timeout = $timeout(myAction, 4000);` with no need for the extra wrapping function. – tavnab Aug 28 '17 at 16:36
  • 1
    Timers do have a callback, the callback is what's executed after the elapsed time. The promise is what is returned. – ste2425 Aug 28 '17 at 16:39
  • @ste2425 its a function which is executed delayed not a `callback` in the original way of thinking. This is indeed a difference. – lin Aug 28 '17 at 16:41
  • @lin we're talking specifically about the 1st argument to `$timeout`. That is a function, and what I'm referring to as the callback.. – tavnab Aug 28 '17 at 16:42
  • @tavnab yep I know and its still not a `callback` function, its a function which is executed delayed. The main properties of an `callback` function are not present while using `$timeout`. =) – lin Aug 28 '17 at 16:44
  • @lin fair enough; in any case, that 1st argument to the second `$timeout` can just be `myAction` :) – tavnab Aug 28 '17 at 16:46
  • @tavnab yea I know. I always keep the answer code closly to the questions code. Thank you. – lin Aug 28 '17 at 16:54
  • @lin Thanks, Simplest fix. Worked like a charm. But still wanted to know if there's some tweak we could perform with the $timeout timer itself instead of cancelling it. – Siena Aug 29 '17 at 05:44
  • 1
    @Siena this is not possible. – lin Aug 29 '17 at 08:20
0

This uses the promise returned by $timeout which gets rejected when the $timeout is canceled. The catch handler rejects the second timer and performs its actions immediately.

$scope.data1_timeout = $timeout(function() {
  // some action
}, 2000);

$scope.data2_timeout = $timeout(function() {
  // some action
}, 4000);

$scope.data1_timeout.catch(function(){
    $timeout.cancel($scope.data2_timeout);
    //same actions here as in data2_timeout
})

It'd make more sense to encapsulate the data2_timeout functionality in a named function and call it from both places like so:

$scope.data1_timeout = $timeout(function() {
  // some action
}, 2000);

function someAction2() {
    //some action
}

$scope.data2_timeout = $timeout(someAction2, 4000);

$scope.data1_timeout.catch(function(){
    $timeout.cancel($scope.data2_timeout);
    someAction2();
})

Note: If the intent is for data2 actions to wait for data1_timeout to complete or be canceled, then instead of data2 being a timeout, just add it as a .finally() callback for the data1_timeout promise.

$scope.data1_timeout = $timeout(function() {
  // some action
}, 2000);

$scope.data1_timeout.finally(function() {
  // do data2 stuff here.
  // Guaranteed to run, after data1_timeout completes or is canceled.
});
JC Ford
  • 6,946
  • 3
  • 25
  • 34