2

All,

i am trying to setup a global httpInterceptor to have a custom popup message when a client timeout appears, not a server one. I found this article: Angular $http : setting a promise on the 'timeout' config , and converted it into a httpInterceptor, but it does not work as expected and has some weird behavior.

 $provide.factory('timeoutHttpInterceptor', function ($q, $translate, $injector) {

        var timeout = $q.defer();

        var timedOut = false;

        setTimeout(function () {
            timedOut = true;
            timeout.resolve();
        }, 10000);
        return {
            request: function (config) {
                config.timeout = timeout.promise;
                return config;
            },
            response: function(response) {
                return response;
            },
            responseError: function (config) {
                if(timedOut) {
                    var toastr = $injector.get('toastr');
                    toastr.custom('network', $translate('title'), $translate('label'), { timeOut: 5000000000000, closeButton: true, closeHtml: '<button></button>' });
                    return $q.reject({
                        error: 'timeout',
                        message: 'Request took longer than 1 second(s).'
                    });
                }
            },
        };
    });
Community
  • 1
  • 1
Ben Croughs
  • 2,566
  • 1
  • 20
  • 30

1 Answers1

4

You can use $timeout service that returns a promise and assign it to config.timeout. Take a look at the code below.

.factory('timeoutInterceptor', ['$q','$timeout', function($q,$timeout) {
    return {
      request: function(config) {
        //assign a promise with a timeout, and set timedOut flag, no need to trigger $digest, thus false as 3rd param
        config.timeout = $timeout(function(){ config.timedOut = true },2000,false);
        return config;
      },
      responseError :function(rejection) {
        if(rejection.config.timedOut){ //if rejected because of the timeout - show a popup 
            alert('Request took longer than 1 second(s).');
        }
        return $q.reject(rejection);
      }
    };

Here is full working example : http://jsfiddle.net/2g1y4bk9/

MiTa
  • 1,340
  • 11
  • 12
  • Thanks a lot for your answer, I implemented it and it works, very useful and super handy jsFiddle. I was looking for that a long time, but could not find the exact implementation for the httpInterceptor, so now other people hopefully can. – Ben Croughs Nov 28 '16 at 13:36
  • After implementing this we found some issues when using Selenium based Protractor tests. We also needed to release the object to make those tests work again. Related issue about protractor: http://stackoverflow.com/questions/26299173/protractors-waitforangular-fails-on-angular-webapp-appium-chrome-on-real-dev add this: response: function(response) { $timeout.cancel(response.config.timeout); return response; }, – Ben Croughs Dec 16 '16 at 14:53