McFiddlyWiddly
McFiddlyWiddly

Reputation: 581

How do I stop a $interval function to execute if the server has not responded yet?

Let me clarify the question:

I have a function in my controller that uses a service to send an HTTP GET request to see if the status is 'done'. This function runs every 5 secs. However, this would also run in every 5 seconds even if there is no response yet, without killing the previous request.

How do I ensure that if there is no response, in 5 secs, that the previous request is killed? Or is there a better solution to this?

Here's my $interval function:

self.$interval(function setInterval() {
    EngineService.getEngines().then(
      function getEngines(response) {
        self.enginesListFromDatabase = response;
        for (const item of self.enginesListFromDatabase) {
          if (item.status === 'done' && self.doneArray.indexOf(item.id) === -1) {
            self.doneArray.push(item.id);
          }
        }
      }
    );
  }, self.interval);

The service has this http call:

  getEngines() {
    return this.$http({
      method: 'GET',
      url: '/api/engines',
    }).then(
         function getResponse(res){
           return res.data;
         }
       );
  }

I tried looking into the docs, but couldn't make sense of how to use $interval properly for this case, or $q.

Upvotes: 1

Views: 88

Answers (2)

MMhunter
MMhunter

Reputation: 1441

You can create a $promise and save it to EngineService for canceling requests.

EngineService.canceler = $q.defer(); // $q is a service u need to inject to EngineService. this is just example that u should assign it to the service
getEngines() {
    return this.$http({
      method: 'GET',
      url: '/api/engines',
      timeout:EngineService.canceler
    }).then(
         function getResponse(res){
           return res.data;
         }
       );
  }

and cancel the last request:

self.$interval(function setInterval() {
    EngineService.canceler.resolve();
    EngineService.getEngines().then(
      function getEngines(response) {
        self.enginesListFromDatabase = response;
        for (const item of self.enginesListFromDatabase) {
          if (item.status === 'done' && self.doneArray.indexOf(item.id) === -1) {
            self.doneArray.push(item.id);
          }
        }
      }
    );
  }, self.interval);

Upvotes: 1

Omri Aharon
Omri Aharon

Reputation: 17064

Regarding your cancelling the request approach - I think it would be much easier to have a variable in your controller (or service) that holds the done/undone status. That way, in each function in the then(..) section, you can ask:

if (!self.done) { 
    ...
}

And then get on in case that's relevant. Otherwise, all requests' responses would fail at that if and nothing would happen, nothing gets overridden.

To cancel future requests -

You can make use of $interval.cancel method and cancel your interval when you're getting your response.

var intervalFunc = $interval(function () { 
        ... 
        if (!self.done && gotMyWay) {
            $interval.cancel(intervalFunc); 
        }
    }, self.interval);

Fiddle demonstrating the cancel mechanism.

Upvotes: 0

Related Questions