0

I'm just testing the timeout functionality with Angular's $http module, however it keeps returning undefined as the response

It's fine if set up just like this, but if I tack on .error(function) instead of .then(function), to the $http call, it throws an error trying to grab the data field from an undefined object

var timeout = $q.defer();

var config = {
        url: 'http://192.168.1.65:3000',
        timeout: timeout.promise,
        method: 'POST'
    };

    $http(config).then(function(res) {
        // This is always undefined when timeout occurs
        console.log(res);
    });

    $timeout(function() {
        console.log('resolving the promise to abort the http call. This works fine');
        timeout.resolve();
    }, 1000);

Any ideas what I'm doing wrong?

rogerdeuce
  • 1,471
  • 6
  • 31
  • 48
gfunk
  • 592
  • 6
  • 13
  • You are not passing a value to your `resolve` call. – Dan May 21 '15 at 20:20
  • I don't believe thats the issue, I just tried as a sanity check and it didn't change anything...according to this other answer this should be all you need – gfunk May 21 '15 at 20:25
  • Are you wanting to timeout your request or cancel it? I had to use something similar to this in my place of work and I don't think `timeout` accepts a promise. If you're looking to cancel your request, set `cancellationToken` to a promise. What other answer did you use? – Dan May 21 '15 at 20:27
  • @gfunk, when the request times out, it is a rejected promise - so you need `.catch` – New Dev May 21 '15 at 20:29
  • oh sorry...this was the answer http://stackoverflow.com/a/21916315/3325262 – gfunk May 21 '15 at 20:44

1 Answers1

3

When $http times-out, it returns a rejected promise that you can handle with .catch:

$http(config)
  .then(function(response){
  })
  .catch(function(error){
     // will fire when timed out
  })

Demo

Off-topic: it's actually simpler to just use the promise generated by $timeout, without the need for $q.defer:

var timeout = $timeout(angular.noop, 1000);
$http.get(url, {timeout: timeout})
     .then(...)
     .catch(...)

EDIT:

In case there is an interceptor, then the timeout would result in responseError, and if defined, that interceptor essentially "handles" the error so it no longer becomes a rejected promise and the result is routed to .then - and if you do not return anything from the responseError function, the data passed to the .then handler is undefined. If you want to keep the rejection, you can do:

// inside http inteceptor
responseError: function(rejection){

  if (rejection.status === 0){ // if timeout
    return $q.reject({reason: "timeout"});
  }
  // ...
}
New Dev
  • 48,427
  • 12
  • 87
  • 129
  • If this is true then why is his `console.log` printing undefined? :s – Dan May 21 '15 at 20:39
  • 1
    @DanPantry, if it's implemented as he states in the question, then it doesn't get there. Maybe something else is printing `"undefined"` – New Dev May 21 '15 at 20:44
  • @NewDev you're right, there was an interceptor in the code that was catching the error and then returning undefined – gfunk May 21 '15 at 20:54
  • 2
    @gfunk, it is quite an essential data point to the question :) – New Dev May 21 '15 at 20:56