【问题标题】:Injected service is undefined right in the constructor在构造函数中未定义注入的服务
【发布时间】:2016-07-06 19:54:16
【问题描述】:

对于注释,我对 Angular 非常陌生(1 或 2 就这点而言)。

我正在尝试编写 Http 的“超级”层,以避免必须将相同的标头放在任何地方。

import {Http, ConnectionBackend, RequestOptions, Response, Headers} from '@angular/http';
import {Observable} from 'rxjs';
import {LoadingService} from "../../services/loading.service";

export class HttpLoading extends Http {
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions,
        private _ls: LoadingService )
    {
        super(backend, defaultOptions);
    }

    getPostPutHeader() {
        var authHeader = new Headers();
        authHeader.append("Authorization", "Bearer "+ localStorage.getItem('token') );
        authHeader.append('Content-Type', 'application/json');
        return authHeader;
    }

    post(url: string, data:any):Observable<Response> {
        this._ls.isLoading = true; // Exception here: this._ls is undefined
        return super.post(url, data, { headers: this.getPostPutHeader() })
            .map(res => {
                this._ls.isLoading = false;
                return res;
            });
    }
}

还有一个服务来判断请求何时执行;它被注入到上面的类 HttpLoading 中。

import {Injectable} from '@angular/core';

@Injectable()
export class LoadingService {
    isLoading: boolean = false;
}

我的引导程序中有很多东西,包括 HttpLoading、LoadingService 和 ConnectionBackend(对于最后一个,如果它不在这里,我会得到一个异常)。

bootstrap(AppComponent, [
    ConnectionBackend,
    HttpLoading,
    APP_ROUTER_PROVIDERS,
    HTTP_PROVIDERS,
    LoadingService,
    disableDeprecatedForms(),
    provideForms()
])

问题是我第一次调用HttpLoadingpost 方法(在另一个服务中),我在this._ls.isLoading 得到一个异常,因为this._ls 是未定义的,我想不通为什么。

如果您需要更多信息,请告诉我。


编辑

LoadingService 已正确注入到我的AppComponent(主要组件)中。

//imports
//@Component
export class AppComponent {
    requesting:boolean = false;

    constructor(public authService: AuthService, private router: Router, private _ls: LoadingService) {
    }

    navigate(route:string) {
        this._ls.isLoading = true;
        this.router.navigate([route])
            .then(() => this._ls.isLoading = false);
    }
}

可能的解决方案

看来您的公共/私有参数必须放在列表的首位。不过,我会让比我更熟练的人解释原因……

export class HttpLoading extends Http {

    constructor(private _ls: LoadingService, backend: ConnectionBackend, defaultOptions: RequestOptions) {
        super(backend, defaultOptions);
}

【问题讨论】:

    标签: angularjs angular angular2-injection


    【解决方案1】:

    在引导您的应用程序时,我会在提供程序中以这种方式配置您的 HttpLoading 类:

    bootstrap(AppComponent, [
      (...)
      HTTP_PROVIDERS,
      {
        provide:Http,
        useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, loadingService: LoadingService) => {
          return new HttpLoading(backend, defaultOptions, loadingService);
        },
        deps: [XHRBackend, RequestOptions, LoadingService]
      }
    ]);
    

    这样做的原因是您想为 Http 提供程序使用自己的类。您需要通过 HttpLoading 类更改 Http 提供程序后面的类。小心在HTTP_PROVIDERS之后定义。

    为了能够将XHRBackend 的实例注入你的类,你需要使用useFactory...

    【讨论】:

    • 您能否解释一下原因,如果这不是太麻烦的话?另外我认为您缺少一个右大括号;我的 IDE 出现错误
    • 我在回答中添加了一些解释...如果它回答了您的问题,请随时告诉我...否则,您是对的。需要删除 { ;-) 感谢您指出这一点!
    • 非常感谢。我仍然不明白一切,但这是一个开始!当我在我的组件中使用 Http 时,会自动将 Http 替换为 HttpLoading 吗?我应该在 HttpLoading 的构造函数中用 XHRBackend 替换 ConnectionBackend 吗?
    【解决方案2】:

    好的,我知道这可能看起来微不足道,但尝试创建一个变量并在构造函数中初始化它

    【讨论】:

    • 我也推荐这个——优化引擎可能会删除对这个依赖的引用。
    • 除了我看不出它是如何工作的,这在任何层面上都不是一个解决方案。在构造函数中注入的服务应该始终在底层上下文中可用。
    【解决方案3】:

    扩展@Thierry Templier 的答案。我正在使用 Angular v4,我的经验是您需要提供扩展构造函数所需的所有依赖项,并且以正确的顺序 - 我想这是从 angular 1.x 开始的传统方式。

    我的例子:

    // 这是我的扩展类(仅相关部分)

    @Injectable()
    export class HttpService extends Http {
    
        constructor(
            backend: ConnectionBackend,
            defaultOptions: RequestOptions,
    
            private router: Router,
            private loaderService: LoaderService,
            private modalService: ModalService,
            private localStorageService: LocalStorageService
        )
        {
            super(backend, defaultOptions)
        }
    

    // 这是在 app.module.ts 中定义的提供者工厂:

    export function httpClientFactory(
            backend: XHRBackend,
            defaultOptions: RequestOptions,
            router: Router,
            loaderService: LoaderService,
            modalService: ModalService,
            localStorageService: LocalStorageService
        ) : Http
    {
        return new HttpService(
            backend,
            defaultOptions,
            router,
            loaderService,
            modalService,
            localStorageService
        );
    }
    

    这是app.module.ts中的配置(只留下相关部分):

    providers: [
        ModalService
        LocalStorageService,
        LoaderService,
        {
            provide: HttpService,
            useFactory: httpClientFactory,
            deps: [XHRBackend, RequestOptions, Router, LoaderService, ModalService, LocalStorageService]
        }
    

    注意:注意config中deps的声明顺序和工厂构造函数的顺序是一样的

    【讨论】:

      猜你喜欢
      • 2018-10-11
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多