【问题标题】:No provider for ConnectionBackend while inheriting from Http从 Http 继承时没有 ConnectionBackend 的提供者
【发布时间】:2017-03-23 07:18:45
【问题描述】:

我正在尝试围绕 Angular 2 中的内置 Http 服务进行包装,以便有可能添加自定义行为(标头、参数等)

所以我创建了一个普通的类(不是服务)并从 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();
  }*/
}

我创建了一个从此类继承的服务,以便以后可以将其注入并用于我的目的。

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

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

error_handler.js:47 例外:未捕获(承诺中):错误:./VehiclesListComponent 类 VehiclesListComponent_Host 中的错误 - 内联模板:0:0 原因:没有 ConnectionBackend 提供程序!

我尝试使用堆栈溢出搜索解决方案,但它看到 HtpModule 应该已经具备正常工作所需的一切。

谁能帮帮我?问题出在哪里?

【问题讨论】:

  • 我也用这个链接作为继承自Http的例子:blog.tomasandtomas.com/…
  • 请将代码作为文本添加到问题中,而不是链接到屏幕截图。
  • 它的格式很奇怪,但我会尝试。
  • 只需选择代码并按下编辑器工具栏中的{}按钮(或使用任何其他方式使每个代码行以至少4个空格开头)
  • 好多了,但它是错误的按钮。片段[&lt;&gt;] 仅适用于可以在问题中实际执行的代码,[{}] 适用于不可运行的代码。

标签: inheritance angular angular2-http


【解决方案1】:

你不能像这样把它添加到提供者中

providers: [ ApplicationService, InspectionHttpService ]

如果你这样做了,那么 Angular 会尝试创建它,但它不会找到 ConnectionBackend 的提供者

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

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

有了这个,你可以将它注入为InspectionHttpService

constructor(private http: InspectionHttpService) {}

如果您希望能够将其注入为Http,则需要将provide 更改为Http 而不是InspectionHttpService。但这会覆盖任何使用常规Http(如果您需要)的能力。

更新

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

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

useFactory: httpFactory

据我记忆,我认为这个错误与 AoT 有关

【讨论】:

  • 伙计,你太棒了!你节省了我的时间。但我怎么会知道这个?我认为我们仍然需要更好的文档,或者我在 angular2 中学习 DI 时丢失了一些东西。非常感谢您这么快的回复!祝你有美好的一天,希望你一切都好)
  • 我收到一个错误 - “没有 XHRBackend 的提供者” - 想法?
  • @Kudoz 你还需要导入HttpModlule
  • 它已导入...我认为这个问题与我导入扩展 HTTP 类的时间有关。我在引导程序中提供它 - 如果我将它作为 ngModule 的一部分提供,它似乎可以工作。
【解决方案2】:

扩展Http服务时,必须为父类注入后端和选项:

@Injectable()
export class HttpInterceptor extends Http {
  constructor(
    backend: XHRBackend,
    options: RequestOptions,
    ...
  ) {
    super(backend, options);
  }
  ...
}

这样您就不必使用工厂,因为 Angular 会自行计算注入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2018-04-24
    • 2018-05-09
    • 2017-02-03
    • 1970-01-01
    相关资源
    最近更新 更多