TonyW
TonyW

Reputation: 18875

AngularJS: timeout promise calls

In my AjaxPromiseService.js factory, I have been trying to incorporate a timeout mechanism into promise calls (usually $http.get/post calls to remote services). The way I am currently doing is to create a race between a $timeout event and the actual promise calls. Example code as following (code from my AjaxPromiseService.js factory in AngularJS): also available in this plnkr

var timeoutObj = {"isTimeout": true};

function timeoutPromise(deferredObj) {
      $timeout(function() {
        console.log("promise timeout");
        deferredObj.resolve(timeoutObj);
        }, timeoutLimit); // timeoutLimit is in milisecond
    }

//promise calls (e.g. $http.get())
function getDummyData(milisec) {
      var data = {"data" : "dummy data from ajax!"};
      var deferred = $q.defer();

      timeoutPromise(deferred); //start the race to see who resolves first

      //use $timeout to mimick an AJAX call
      $timeout(function() {
        deferred.resolve(data);
        $timeout.cancel(timeoutPromise(deferred)); //not working, how to cancel the race here?
      }, milisec); //

      return deferred.promise;

    } //getDummyData

This seems working, if getDummyData() is not resolved within the specified duration, the timeoutPromise() will return the useful flag so I can let the AJAX calls fail gracefully. Both timeoutPromise() and getDummyData() will resolve eventually in a sequential order, however, I would like to cancel timeoutPromise() if getDummyData() is reslolved first. I was wondering how to do this?

Upvotes: 2

Views: 3024

Answers (3)

Michel
Michel

Reputation: 28289

According to $http documentation, the timeout property of the $http configuration accepts either a promise, either a number in milliseconds:

timeout{number|Promise}timeout in milliseconds, or promise that should abort the request when resolved.

Therefore the solution is straightforward:

function getData () {
    return $http.get(someUrl, {timeout: 3000});  // adjust the value to what you need
}

Upvotes: 1

Michael Kang
Michael Kang

Reputation: 52847

If you're using $http, there is a much simpler option. Use timeout property of $http configuration object, and $timeout service:

var requestTimeout = $timeout(function() {}, 4000);
$http({ method:'GET', url:'...', timeout: requestTimeout});
requestTimeout.then(function() {
   console.log ('request aborted - timed out!');
});

The $timeout will automatically be aborted when the request succeeds within the timeout period.

Upvotes: 1

New Dev
New Dev

Reputation: 49590

$http has a timeout parameter, which times out the request when a promise is resolved - so, you could give it a $timeout promise:

getData: function(input, timeout){
  var timeoutPromise = timeout ? $timeout(function(){}, timeout) : null;

  return $http({url: "/some/url",
                timeout: timeoutPromise,
                method: "GET"
               }).then(function(response){
                  var data = response.data;
                  // do something with data, if needed
                  return data;
               });
}

DEMO

Upvotes: 3

Related Questions