问题
I am trying to make a wrapper around built in Http service in angular 2 to have a possibility to add custom behaviour (headers, parameters etc.)
So I created a usual class (not a service) and inherit it from Http. Class definition
import {
Http,
ConnectionBackend,
RequestOptions,
RequestOptionsArgs,
Headers
} from '@angular/http';
import { Observable } from 'rxjs/Observable';
import {tamamApiUrl} from '../constants';
import {CustomQueryEncoder} from './CustomQueryEncoder';
import 'rxjs/Rx';
export class BaseHttp extends Http {
protected applicationDataService;
protected baseUrl: string = tamamApiUrl;
protected encoder: CustomQueryEncoder;
constructor(backend:ConnectionBackend,
defaultOptions: RequestOptions, applicationDataService: any) {
super(backend, defaultOptions);
this.applicationDataService = applicationDataService;
}
get(url: string, options?: RequestOptionsArgs): Observable<any> {
this.addDefaultOptions(options);
return super.get(url, options);
}
post(url: string, body: any, options?: RequestOptionsArgs): Observable<any> {
this.addDefaultOptions(options);
this.addDefaultPostOptions(options);
return super.post(url, body, options);
}
private addDefaultOptions(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
const applicationData = this.applicationDataService.getApplicationData();
if (applicationData.applicationKey) {
options.headers.append('application-id', applicationData.applicationKey);
}
if (applicationData.secretKey) {
options.headers.append('secret-key', applicationData.secretKey);
}
if (applicationData.userToken) {
options.headers.append('user-token', applicationData.userToken);
}
return options;
}
private addDefaultPostOptions(options): void {
options.headers.append('Content-Type', 'application/json');
}
/*private requestInterceptor(): void {
this.loaderService.showPreloader();
}
private responseInterceptor(): void {
this.loaderService.hidePreloader();
}*/
}
Than I Created a service which inherited from this class so that I can inject it later and use for my purposes.
import { Headers, URLSearchParams } from '@angular/http';
import {tamamRootUrl} from '../constants';
import {BaseHttp} from '../api/BaseHttp';
import { Injectable } from '@angular/core';
import {
ConnectionBackend,
RequestOptions,
} from '@angular/http';
import {ApplicationService} from './ApplicationService';
@Injectable()
export class InspectionHttpService extends BaseHttp{
protected baseUrl: string = tamamRootUrl;
protected params: URLSearchParams = new URLSearchParams();
constructor(backend: ConnectionBackend,
defaultOptions: RequestOptions, protected applicationService: ApplicationService) {
super(backend, defaultOptions, applicationService);
}
getRootUrl() {
return this.baseUrl;
}
}
Service definition
After I try to inject created service in component I receive an error:
error_handler.js:47 EXCEPTION: Uncaught (in promise): Error: Error in ./VehiclesListComponent class VehiclesListComponent_Host - inline template:0:0 caused by: No provider for ConnectionBackend!
I tried to search solution using stack-overflow but it see,s that HtpModule should already have all necessary for a proper work.
Could anyone help me? Where is the problem?
回答1:
You can't just add it to the providers like this
providers: [ ApplicationService, InspectionHttpService ]
If you do, then Angular will try to create it, and it won't find a provider for ConnectionBackend
You need to use a factory, where you can just pass the XHRBackend
(which implements ConnectionBackend
)
imports: [HttpModule],
providers: [
ApplicationService,
{
provide: InspectionHttpService,
deps: [XHRBackend, RequestOptions, ApplicationService],
useFactory: (backend, options, aplicationService) => {
return new InspectionHttpService(backend, options, applicationService);
}
}
]
With this, you can inject it as InspectionHttpService
.
constructor(private http: InspectionHttpService) {}
If you want to be able to inject it as Http
, then you need to change the provide
to Http
instead of InspectionHttpService
. But this overrides any ability to use the regular Http
if you ever need it.
UPDATE
In some environments, it's possible you may get an error with the above code. I forgot the exact error message, but it will give you a proposed solution of extracting the factory function, i.e.
export function httpFactory(backend: XHRBackend, options: RequestOptions,
service: ApplicationService) {
return new InspectionHttpService(backend, options, service);
}
useFactory: httpFactory
From what I remember, I think the error has something to do with AoT
回答2:
When extending the Http service, you have to inject backend and options for the parent class:
@Injectable()
export class HttpInterceptor extends Http {
constructor(
backend: XHRBackend,
options: RequestOptions,
...
) {
super(backend, options);
}
...
}
This way you don't have to use a factory because Angular will figure the injection on its own.
来源:https://stackoverflow.com/questions/40507670/no-provider-for-connectionbackend-while-inheriting-from-http