Title: How angular interceptors works?
Tags: javascript;angularjs
Question: I was learning angular interceptors today. I did some samples to to better understand the concept. Here is small sample.



```var app = angular.module("myApp", []);

app.factory("timestampMaker", [
  function() {
    var timestampMaker = {
      request: function(config) {
        console.log(config);
        config.requestTimestamp = new Date().getTime();
        return config;
      },
      response: function(response) {

        response.config.responseTimestamp = new Date().getTime();
        return response;
      }
    };
    return timestampMaker;
  }
]);

app.config(['$httpProvider',
  function($httpProvider) {
    $httpProvider.interceptors.push('timestampMaker');
  }
]);

app.run(function($http) {
  $http.get('https://api.github.com/users/naorye/repos').then(function(response) {
    console.log(response);
    var time = response.config.responseTimestamp - response.config.requestTimestamp;
    console.log("The request took" + (time / 1000) + "seconds")
  });
});```
```<html ng-app="myApp"&gt;

<head&gt;
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"&gt;</script&gt;
</head&gt;

</html&gt;```




When I am doing ```console.log(config)``` inside request function, here is the output on the console.


I am not getting how ```responseTimestamp``` appear in the config object of request where as  its defined inside response function



Here is another answer: Note I used the source code for 1.2.x which is the one added in the question.

```$httpProvider``` is a provider that gives you ```$http``` service.

As a provider, in config time exposes a public array - there you just add all strings from services names you wanted to be injected in your response/requests.

That is what you do here

```app.config(['$httpProvider',
  function($httpProvider) {
    $httpProvider.interceptors.push('timestampMaker');
  }
]);
```

and it can be only done in config time because per docs providers can be configured before the application starts

You can see the exposed array in the source code in line 159

```var responseInterceptorFactories = this.responseInterceptors = [];
```

When you request the ```$http``` service, injecting it into your service/controller, 
```$get``` function is executed. In that function, your array of interceptors is iterated, as you can see in source code in line  179

```   var reversedInterceptors = [];
   forEach(responseInterceptorFactories, function(interceptorFactory, index) {
      var responseFn = isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory);

      /**
       * Response interceptors go before "around" interceptors (no real reason, just
       * had to pick one.) But they are already reversed, so we can't use unshift, hence
       * the splice.
       */
      reversedInterceptors.splice(index, 0, {
        response: function(response) {
          return responseFn($q.when(response));
        },
        responseError: function(response) {
          return responseFn($q.reject(response));
        }
      });
    });
```

Per convention, they reverse the order. You can see that using the string, they get a reference to the function using ```$injector.get``` or ```$injector.invoke```, and using ```$q.when()``` we can introduce them to the promises chain, even if they are synchronous code - See this Can I use $q.all in AngularJS with a function that does not return a .promise? if you are not sure what I meant about ```$q.when()```

So far we have an array with functions, which are all promise-like (thanks to ```$q.when()```). When you request data through ```$http``` like this

```$http.get('https://api.github.com/users/naorye/repos').then(function(response) {
    console.log(response);
    var time = response.config.responseTimestamp - response.config.requestTimestamp;
    console.log("The request took" + (time / 1000) + "seconds")
  });
```

even though you have the ```.get()```, is just a shortcut for all the same functionality which is here

In the code the relevant part is this one:

First, a chain array is created with two values: an inner function which is not important for our purpose (but it returns a promise - this is important), and undefined value. 

Our array with interceptors is iterated, and request interceptors are added at the beginning (before the request) and response at the end. Like this 

```   function serverRequest {
      // some code
    };
     var chain = [serverRequest, undefined];
    var promise = $q.when(config);

    // apply interceptors
    forEach(reversedInterceptors, function(interceptor) {
      if (interceptor.request || interceptor.requestError) {
        chain.unshift(interceptor.request, interceptor.requestError);
      }
      if (interceptor.response || interceptor.responseError) {
        chain.push(interceptor.response, interceptor.responseError);
      }
    });
```

then, having the chain complete (remember our array of interceptors was full of promises), the code iterates it, adding all of them using ```.then()```, causing all of them to be executed in a chain, following promises chaining (you can google that)

```    while(chain.length) {
      var thenFn = chain.shift();
      var rejectFn = chain.shift();

      promise = promise.then(thenFn, rejectFn);
    }
```

Finally, the callback you add in ```success``` and ```error``` is added at the very end of the chain and the promise is returned

``` promise.success = function(fn) {
  promise.then(function(response) {
    fn(response.data, response.status, response.headers, config);
  });
  return promise;
};

promise.error = function(fn) {
  promise.then(null, function(response) {
    fn(response.data, response.status, response.headers, config);
  });
  return promise;
};

return promise;
```

The only part I am not sure about is the use of ```undefined``` in the chain array

Summary

You add the name for your services, ```$HttpProvider``` uses ```$invoke``` service to get them and adds them in the promise chain using ```$q.when()```, returning a promise. At the end of that, your callbacks for a specific ```$http``` request is added.


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2016:00:08/20/16', 'FavoriteCount': 1.0, 'PostTypeId': 1, 'Tags': '<javascript><angularjs>', 'Title': 'How angular interceptors works?', 'ViewCount': 307, 'id': 39054862, 'user_AboutMe': '<p>I am a Web Developer in ColdFusion/ Ruby on Rails.</p>\n\n<p>My Blog: <a href="http://cfdeepak.wordpress.com/" rel="nofollow noreferrer">http://cfdeepak.wordpress.com/</a></p>\n', 'user_AccountId': 1411058.0, 'user_DisplayName': 'Deepak Kumar Padhy', 'user_Reputation': 3848.0, 'user_Views': 475.0, 'user_id': 1337630.0}}