Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No provider for XHRBackend with Angular 2 and Http service

I'm building a project based on angular2 (angularcli generated), webpack, scss, and module oriented.

For http request I decided to create a Service that is used by an Authentication service.

All referenced in a CoreModule

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RequestOptions, XHRBackend} from '@angular/http';

// Services
import {HttpService} from './services/http.service';
import {AuthService} from './services/auth/auth.service';

export function httpInterceptor(backend: XHRBackend,
                                defaultOptions: RequestOptions) {
  return new HttpService(backend, defaultOptions);
}


@NgModule({
  imports: [
    CommonModule
  ],
  providers: [
    AuthService,
    {
      provide: HttpService,
      useFactory: httpInterceptor,
      deps: [XHRBackend, RequestOptions]
    }
  ]
})
export class CoreModule {
}

And my AppModule :

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {Router} from '@angular/router';

import 'materialize-css';

// Components
import {AppComponent} from './app.component';

// Modules
import {MaterializeModule} from 'angular2-materialize';
import {AppRoutingModule} from './app-routing.module';
import {CoreModule} from './core/core.module';
import {AuthModule} from './auth/auth.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    MaterializeModule,
    CoreModule,
    AuthModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(router: Router) {
    console.log('Routes: ', JSON.stringify(router.config, undefined, 2));
  }
}

Here is the full issue :

ERROR Error: Uncaught (in promise): Error: No provider for XHRBackend!
Error: No provider for XHRBackend!
    at injectionError (core.es5.js:1169)
    at noProviderError (core.es5.js:1207)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._throwOrNull (core.es5.js:2649)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKeyDefault (core.es5.js:2688)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKey (core.es5.js:2620)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_.get (core.es5.js:2489)
    at resolveNgModuleDep (core.es5.js:9562)
    at _callFactory (core.es5.js:9637)
    at _createProviderInstance$1 (core.es5.js:9576)
    at resolveNgModuleDep (core.es5.js:9558)
    at injectionError (core.es5.js:1169)
    at noProviderError (core.es5.js:1207)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._throwOrNull (core.es5.js:2649)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKeyDefault (core.es5.js:2688)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKey (core.es5.js:2620)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_.get (core.es5.js:2489)
    at resolveNgModuleDep (core.es5.js:9562)
    at _callFactory (core.es5.js:9637)
    at _createProviderInstance$1 (core.es5.js:9576)
    at resolveNgModuleDep (core.es5.js:9558)
    at resolvePromise (zone.js:770)
    at resolvePromise (zone.js:741)
    at zone.js:818
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424)
    at Object.onInvokeTask (core.es5.js:3924)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (zone.js:191)
    at drainMicroTaskQueue (zone.js:584)
    at <anonymous>
defaultErrorLogger @ core.es5.js:1020
webpackJsonp.../../../core/@angular/core.es5.js.ErrorHandler.handleError @ core.es5.js:1080
next @ core.es5.js:4562
schedulerFn @ core.es5.js:3635
webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:238
webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.next @ Subscriber.js:185
webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next @ Subscriber.js:125
webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next @ Subscriber.js:89
webpackJsonp.../../../../rxjs/Subject.js.Subject.next @ Subject.js:55
webpackJsonp.../../../core/@angular/core.es5.js.EventEmitter.emit @ core.es5.js:3621
webpackJsonp.../../../core/@angular/core.es5.js.NgZone.triggerError @ core.es5.js:3993
onHandleError @ core.es5.js:3954
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.handleError @ zone.js:395
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runGuarded @ zone.js:157
_loop_1 @ zone.js:653
api.microtaskDrainDone @ zone.js:662
drainMicroTaskQueue @ zone.js:592
like image 873
An-droid Avatar asked Jun 22 '17 13:06

An-droid


2 Answers

You need to import the HttpModule in your module. The latter provides the HTTP providers including XHRBackend. Moreover if you want to implement interception for HTTP request, you need to use the Http type when registering your interceptor implementation (a sub class of Http).

Here is a sample:

imports: [
  (...)
  HttpModule, // <-------------
  (...)
],
providers: [
  {
    provide: Http, // <-------------
    useFactory: httpInterceptor,
    deps: [ XHRBackend, RequestOptions, Store, Injector ]
  }
]
like image 55
Thierry Templier Avatar answered Sep 28 '22 15:09

Thierry Templier


You are not referencing the context (If I'm correct), try with an arrow function:

return () => new HttpService(backend, defaultOptions);

Anyways, why don't you add to your AppModule, in the imports, the module of Http (HttpModule)?

AppModule:

import { HttpModule } from '@angular/http';

imports: [ HttpModule ]

And in your service you just:

import { Injectable } from '@angular/core';
import { Http, Headers, Response, XHRBackend } from '@angular/http';

@Injectable()
export class MyService {

    constructor(private http: Http) {
         }

// Use Http's stuff
}

Then in your CoreModule you can just add:

providers: [ MyService ]
like image 21
SrAxi Avatar answered Sep 28 '22 15:09

SrAxi