2

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?

3 Answers 3

3

$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

Sign up to request clarification or add additional context in comments.

5 Comments

return $http().then() returns a promise... I'm not sure what you're asking otherwise - a promise of what?
so you don't need to wrap $q.defer() in $http() to return a promise?
@TonyGW, one rarely does when the function itself returns a promise, like $http and $timeout do... in fact, it would be a deferred anti-pattern
but in the timeoutPromise, if I want to return a promise object that has a flag {isTimeout: true}, do I need $q to create a promise for return?
timeoutPromise in your question or in my answer? do you mean to return it to the user of getData? Where is it going to be used - in the promise handler or by the caller? In other words, I don't fully understand your new requirement. I suggest you either edit your question with clarification or create a new question
1

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.

Comments

1

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.