【问题标题】:How to Load Environment Data for app.modules.ts in Angular如何在 Angular 中为 app.modules.ts 加载环境数据
【发布时间】:2020-07-22 05:04:03
【问题描述】:

我需要从包含环境数据的服务中加载数据。我需要app.modules 中的模块的一些数据。

这是一个小的app.modules.ts 示例:

import { CustomEnvironmentService } from './CustomEnvironmentService';

let customService: CustomEnvironmentService;

@NgModule({
    declarations: [...],
    imports: [CustomModule.forRoot(customService.ENVIRONMENT_DATA)],
    providers: [...]
})
export class AppModule {}

首先要注意的是customService.ENVIRONMENT_DATA 只是CustomEnvironmentService 中的一个公共变量,它从名为env.js 的环境配置文件中获取信息。

问题是应用加载时customService.ENVIRONMENT_DATA 未定义。这是可以理解的,因为我很确定服务没有初始化,也没有获取数据。

我发现了一个名为 APP_INITIALIZER 的东西,但我似乎无法使用它从 env.js 文件中读取,或者它会使用我的 CustomEnvironmentService(它从 env.js 获取数据)。

我的实现也是基于这篇文章:How to use environment variables to configure your Angular application without a rebuild

有什么想法吗?

【问题讨论】:

  • customService.ENVIRONMENT_DATA 类型的变量? CustomModule 真的是自定义模块还是 3rd 方模块?
  • 您能否提供您的CustomEnvironmentService 的代码,这样会更容易理解发生了什么。这是不是 Angular 服务?
  • 我在这里寻找的是一个来自配置文件的 json obj,它被注入到CustomModule.forRoot(jsonData)。 CustomModule 是需要 json 配置的真实模块的伪代码。我需要该 json 可以在环境之间进行配置。 customService.ENVIRONMENT_DATA 也是表示可能的服务实现的伪代码 - 它不一定是服务......它只需将数据加载到 CustomModule.forRoot({injected data here or globally})
  • 到目前为止你尝试过什么?正如您所暗示的,使用APP_INITIALIZER 是我的建议。您的问题是询问如何从文件中加载 env 数据(您链接到的文章回答了该文件),但您不是在询问有关您面临的特定问题或有关您尝试过的任何细节的问题。
  • 您的要求仍然不完全清楚。您的CustomEnvironmentService 是如何设置的?你对APP_INITIALIZER 做了什么尝试?如果没有足够的信息来说明您目前正在做什么 - 这样我们就可以重现您遇到的问题 - 我们都只会在黑暗中刺伤。

标签: javascript angular configuration


【解决方案1】:

我不确定它运行的确切时间,但您可以使用 APP_INITIALIZER 从文件中读取。

app.module.ts

export function startupServiceFactory(startupService: StartupService) {
    return () => startupService.load();
}

@NgModule({
    ...
    providers: [
        StartupService,
        {
            provide: APP_INITIALIZER,
            useFactory: startupServiceFactory,
            deps: [StartupService],
            multi: true
        }
    ]
})

startup.service.ts

export class StartupService {
    // I just use private properties on the class to hold the returned values
    private localStartupData: any;

    constructor(private httpClient: HttpClient){}

    load(): any {
        // I'm returning a txt file so I have to set the responseType to text
        this.httpClient.get('<relativePathToFile>/env.js', { responseType: 'text' })
        .pipe(
            catchError((err) => {
                // If I have any defaults in case of file not existing I set them here
                return throwError(err);
            })
        )
        .toPromise()
        .then((data: any) => {
            this.localStartupData = data;
        })
        .catch((err: any) => {
            Promise.resolve();
        });
    }

    get startupData(): any {
        return this.localStartupData;
    }
}

只需确保 env.js 包含在您的 angular.json 中

【讨论】:

  • 这行不通,因为我想之前会调用 forRoot 方法
  • 我也不知道时间。不过,它可以使用 APP_INITIALIZER 读取文件
【解决方案2】:

使用您链接的文章中的方法,您不能使用APP_INITIALIZER,因为在所有导入的模块都初始化了您已经发现的内容之后,它们会被调用。

由于这种方法只是将环境设置设置为全局窗口属性__env,因此您只需在 Angular 中定义一个全局常量,您可以从窗口中分配环境设置的值。然后它将在所有应用程序中可用。这也将在应用程序启动时立即可用。

例如,您创建一个environment-data.ts 文件,其内容如下:

export const ENVIRONMENT_DATA = window['__env'];

然后只需在需要的地方导入常量并使用它。

import { ENVIRONMENT_DATA } from './environment-data';

@NgModule({
    declarations: [...],
    imports: [CustomModule.forRoot(ENVIRONMENT_DATA)],
    providers: [...]
})
export class AppModule {}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 2017-09-10
    相关资源
    最近更新 更多