【问题标题】:Problem accessing service from export function从导出功能访问服务时出现问题
【发布时间】:2021-03-18 23:10:30
【问题描述】:

我想从导出功能访问我的角度服务。

我阅读了 SO 中的所有相关问题,但由于某种原因,这些解决方案对我不起作用。

我添加了 app-injector.ts 助手。它看起来像这样:

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

/**
 * Allows for retrieving singletons using `AppInjector.get(MyService)` (whereas
 * `ReflectiveInjector.resolveAndCreate(MyService)` would create a new instance
 * of the service).
 */
export let AppInjector: Injector;

/**
 * Helper to set the exported {@link AppInjector}, needed as ES6 modules export
 * immutable bindings (see http://2ality.com/2015/07/es6-module-exports.html) for
 * which trying to make changes after using `import {AppInjector}` would throw:
 * "TS2539: Cannot assign to 'AppInjector' because it is not a variable".
 */
export function setAppInjector(injector: Injector) {
    if (AppInjector) {
        // Should not happen
        console.error('Programming error: AppInjector was already set');
    } else {
        AppInjector = injector;
    }
}

我将注入器添加到 AppModule 构造函数中,并从其主体中调用 SetAppInector,如下所示:

export class AppModule {
    constructor(injector: Injector) {
        setAppInjector(injector);
    }
}

而且,我使用 AppInjector 将服务注入到我的 AppModule 中声明的 getTranslatedPaginatorIntl() 函数中:

export function getTranslatedPaginatorIntl() {
    const translate = AppInjector.get(TranslateService);
    const paginatorIntl = new MatPaginatorIntl();

    paginatorIntl.itemsPerPageLabel = translate.instant('Items per page');
    paginatorIntl.nextPageLabel = translate.instant('Next page');
    paginatorIntl.previousPageLabel = translate.instant('Previous page');
    // paginatorIntl.getRangeLabel = serbianRangeLabel;

    return paginatorIntl;
}

该函数在@NgModule 声明的提供者部分中被调用(我猜这就是问题所在,因为构造函数可能在此之后被调用,因此注入器不会被及时注入):

providers: [
        ApiService,
        LoaderService,
        { provide: MatPaginatorIntl, useValue: getTranslatedPaginatorIntl() },
        { provide: LocationStrategy, useClass: HashLocationStrategy },
        { provide: MAT_DIALOG_DATA, useValue: {} },
        { provide: MatDialogRef, useValue: {} },
    ]

【问题讨论】:

  • 你为什么用useValue而不是useFactory?很确定这会解决你的问题。只需将你的服务注入到那个工厂函数中,你就可以不用这些丑陋的注入器黑客了。

标签: angular typescript


【解决方案1】:

您无需破解注入器的方法 - Angular 为您的用例提供了受支持的 API。而不是{ provide: Service, useValue: someFunc() },你可以告诉Angular你想使用带有可选依赖的工厂函数{ provide: Service, useFactory: myFactoryFunc, deps: [MyDepService] }

在你的情况下,它看起来像这样:

// The factory function (now with transateService as parameter!)
export const getTranslatedPaginatorIntl = (translateService:TranslateService) => {
    const paginatorIntl = new MatPaginatorIntl();

    paginatorIntl.itemsPerPageLabel = translate.instant('Items per page');
    paginatorIntl.nextPageLabel = translate.instant('Next page');
    paginatorIntl.previousPageLabel = translate.instant('Previous page');

    return paginatorIntl;
}

在你的 app.module 中:

providers: [
    ApiService,
    LoaderService,
    { provide: LocationStrategy, useClass: HashLocationStrategy },
    { provide: MAT_DIALOG_DATA, useValue: {} },
    { provide: MatDialogRef, useValue: {} },
    { 
        provide: MatPaginatorIntl, 
        // The factory function (don't call the function here, angular will do that for you! 
        useFactory: getTranslatedPaginatorIntl, 
        // Provide your dependencies, they will become parameters for the function when angular calls it
        deps: [TranslateService] 
    },
]

更多解释和细节,我建议official angular documentation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 2011-04-22
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多