Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency errors in Angular when creating an $http interceptor as a standalone module

Here is a working example of how I have set up an interceptor which attaches an authentication token to each request (this is more or less the example from https://docs.angularjs.org/api/ng/service/$http)

angular.module("app", [])
.config(function ($httpProvider) {
  $httpProvider.interceptors.push("authInterceptor");
})
.factory("authInterceptor", function ($q) {
  return {
  // interceptor configuration here
  }
})

I have a lot of other stuff in my config and run blocks which call and initiate services from different angular modules, so I want to tidy things up a bit. However I understand there are some very specific rules to dependency injection in config blocks, which I don't quite understand, and these are preventing me from defining my authInterceptor factory in a separate module. As other logic in the config and run blocks calls other modules in the app, declaring that interceptor right there looks out of place.

This is what I want to do:

angular.module("services.authInterceptor", [])
.factory("authInterceptor", function ($q) {
  return {
  // interceptor configuration here
  }
});

angular.module("app", [
 "services.authInterceptor"
]).config(function ($httpProvider, authInterceptor) {
  $httpProvider.interceptors.push("authInterceptor");
});

// Error: Unknown provider authInterceptor.

I tried injecting it to the run block instead, but I guess you're not allowed to inject $httpProvider there:

angular.module("app", [
  "services.authInterceptor"
]).run(function ($httpProvider, authInterceptor) {
  $httpProvider.interceptors.push("authInterceptor");
});

// Error: Unknown provider: $httpProviderProvider <- $httpProvider

Where should I inject the module so that $httpProvider is also injectable, and where should I add the interceptor to existing ones? My main goal is keeping the interceptor and other similar services in their own self-containing modules.

EDIT

I get a different error which seems to be getting me closer when I declare a provider instead of factory (for some reason I always thought these were interchangeable):

angular.module("services.authInterceptor")
.provider("authInterceptor", function ($q) {
  return {}
})

// Error: Unknown provider: $q

So it now successfully injects authInterceptor to my config block, but fails when trying to find $q.

like image 680
Elise Avatar asked May 07 '14 20:05

Elise


People also ask

How do you create an angular interceptor?

Create an Interceptor To do this, create an injectable class that implements HttpInterceptor. Any interceptor we want to create needs to implement the HttpInterceptor interface. This means that our new class should have a method called intercept with parameters HttpRequest and HttpHandler.

Can we have multiple interceptors in angular?

After providing HTTP_INTERCEPTORS we need to inform the class we are going to implement our interceptor into by using useClass. Setting multi to true, makes sure that you can have multiple interceptors in your project.

What is the purpose of interceptors in angular?

The angular interceptor is a medium connecting the backend and front-end applications. Whenever a request is made, the interceptors handle it in between. They can also identify the response by performing Rxjs operators. The interceptors do not initiate the handle method and handle the requests at their level.

How do you create an interceptor in angular 11?

To create an Interceptor, we need to implement the HttpInterceptor interface from @angular/common/http package. Every time our application makes an HTTP request using the HttpClient service, the Interceptor calls the intercept() method.


1 Answers

During the configuration phase only providers and constants can be injected. This is to prevent instantiation of services before they have been fully configured.

This is why you register interceptors by name (pushing the name as a string into the $httpProvider.interceptors array). They will be resolved later during runtime.

This is exactly what you did in your working example, and what you need to do in your second, even when the interceptor is in another module:

angular.module("services.authInterceptor", [])
.factory("authInterceptor", function ($q) {
  return {
  // interceptor configuration here
  }
});

angular.module("app", ["services.authInterceptor"])
.config(function ($httpProvider) {
  $httpProvider.interceptors.push('authInterceptor');
});

Demo: http://plnkr.co/edit/A8SgJ87GOBk6mpXsoFuZ?p=preview

like image 165
tasseKATT Avatar answered Sep 20 '22 15:09

tasseKATT