从Http继承时没有ConnectionBackend的提供者

Nic*_*nko 12 inheritance angular2-http angular

我试图在角度2中内置Http服务的包装器,以便有可能添加自定义行为(标题,参数等)

所以我创建了一个通常的类(不是服务)并从Http继承它. 类定义

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();
  }*/
}
Run Code Online (Sandbox Code Playgroud)

比我创建了一个从这个类继承的服务,以便我可以在以后注入并用于我的目的.

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

服务定义

在我尝试在组件中注入创建的服务后,我收到一个错误:

error_handler.js:47 EXCEPTION:未捕获(在承诺中):错误:./VehiclesListComponent类中的错误VehiclesListComponent_Host - 内联模板:0:0引起:没有ConnectionBackend的提供者!

我尝试使用堆栈溢出搜索解决方案,但它看到,HtpModule应该已经拥有正常工作所需的全部内容.

谁能帮助我?问题出在哪儿?

Pau*_*tha 15

你不能只是像这样将它添加到提供者

providers: [ ApplicationService, InspectionHttpService ]
Run Code Online (Sandbox Code Playgroud)

如果你这样做,那么Angular将尝试创建它,并且它将找不到提供者 ConnectionBackend

你需要使用一个工厂,你可以在那里通过XHRBackend(实施ConnectionBackend)

imports: [HttpModule],
providers: [
  ApplicationService,
  {
    provide: InspectionHttpService,
    deps: [XHRBackend, RequestOptions, ApplicationService],
    useFactory: (backend, options, aplicationService) => {
      return new InspectionHttpService(backend, options, applicationService);
    }
  }
]
Run Code Online (Sandbox Code Playgroud)

有了它,你可以将其注入InspectionHttpService.

constructor(private http: InspectionHttpService) {}
Run Code Online (Sandbox Code Playgroud)

如果您希望能够将其注入Http,则需要更改provideHttp而不是InspectionHttpService.但是Http如果你需要它,这将覆盖任何使用常规的能力.

UPDATE

在某些环境中,您可能会遇到上述代码的错误.我忘记了确切的错误信息,但它会给你一个提取工厂功能的建议解决方案,即

export function httpFactory(backend: XHRBackend, options: RequestOptions,
                            service: ApplicationService) {
  return new InspectionHttpService(backend, options, service);
}

useFactory: httpFactory
Run Code Online (Sandbox Code Playgroud)

根据我的记忆,我认为错误与AoT有关

  • 伙计,你真棒!你们节省了我的时间.但我怎么知道呢?我认为我们仍然需要更好的文档,或者在angular2中学习DI时丢失了一些东西.非常感谢您的快速回复!祝你有愉快的一天,希望你做得好 (2认同)