admin管理员组

文章数量:1335138

I need to load data from a service which contains environment data. I need some of that data for a module in app.modules.

Here's a small app.modules.ts example:

import { CustomEnvironmentService } from './CustomEnvironmentService';

let customService: CustomEnvironmentService;

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

First thing to notice is that customService.ENVIRONMENT_DATA is just a public variable in CustomEnvironmentService which gets information from an environment config file called env.js.

The problem is that when the app loads customService.ENVIRONMENT_DATA is undefined. This is understandable as I'm pretty sure the service isn't initialized and hasn't fetched the data.

I found something called APP_INITIALIZER but it appears that I may not be able to use it to read from either that env.js file or will it use my CustomEnvironmentService (which gets the data from env.js).

I'm also basing my implementation on this article: How to use environment variables to configure your Angular application without a rebuild

Any ideas?

I need to load data from a service which contains environment data. I need some of that data for a module in app.modules.

Here's a small app.modules.ts example:

import { CustomEnvironmentService } from './CustomEnvironmentService';

let customService: CustomEnvironmentService;

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

First thing to notice is that customService.ENVIRONMENT_DATA is just a public variable in CustomEnvironmentService which gets information from an environment config file called env.js.

The problem is that when the app loads customService.ENVIRONMENT_DATA is undefined. This is understandable as I'm pretty sure the service isn't initialized and hasn't fetched the data.

I found something called APP_INITIALIZER but it appears that I may not be able to use it to read from either that env.js file or will it use my CustomEnvironmentService (which gets the data from env.js).

I'm also basing my implementation on this article: How to use environment variables to configure your Angular application without a rebuild

Any ideas?

Share Improve this question edited Apr 10, 2020 at 16:32 razorsyntax asked Apr 9, 2020 at 14:28 razorsyntaxrazorsyntax 3593 gold badges8 silver badges44 bronze badges 7
  • customService.ENVIRONMENT_DATA type of variable? CustomModule is really custom or 3rd party module? – Gourav Garg Commented Apr 15, 2020 at 18:28
  • Can you provide the code for your CustomEnvironmentService then it will be easier to understand what is going on. Is this an Angular service or not? – Aleš Doganoc Commented Apr 15, 2020 at 21:57
  • What I'm looking for here is a json obj from a config file that gets injected into CustomModule.forRoot(jsonData). CustomModule is pseudocode for a real module that requires a json configuration. I need that json to be configurable between environments. customService.ENVIRONMENT_DATA is also pseudocode representing a possible service implementation- it doesn't have to be a service... it just has to load data into CustomModule.forRoot({injected data here or globally}). – razorsyntax Commented Apr 16, 2020 at 13:03
  • 1 What have you tried so far? Using an APP_INITIALIZER would be my suggestion, as you've alluded to. Your question is asking what to do to load env data from a file (which the article you linked to answers), but you're not asking a question about a specific problem you're facing or any details about what you've tried. – Geoff James Commented Apr 16, 2020 at 16:31
  • 1 It's still not entirely clear what you're asking. How is your CustomEnvironmentService being set up? What did you try with APP_INITIALIZER? Without enough information as to what you're currently doing - so that we might be able to reproduce the issue you're having - we'd all just be stabbing in the dark. – Geoff James Commented Apr 17, 2020 at 18:07
 |  Show 2 more ments

2 Answers 2

Reset to default 6 +50

Using the approach from the article you link you cannot use an APP_INITIALIZER because they get called after all the imported modules have initialized what you already discovered.

Since this approach just sets the environment settings as a global window property __env you can just define a global constant in Angular that you assign the value of the environment settings from the window. Then it will be available in all the application. This will be available also immediately when the application starts.

For example you create an environment-data.ts file with the following content:

export const ENVIRONMENT_DATA = window['__env'];

Then just import the constant where you need it and use it.

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

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

I'm not sure on the exact timings as to when it runs but you can read from a file using 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;
    }
}

Just make sure that env.js is included in your angular.json

本文标签: javascriptHow to Load Environment Data for appmodulests in AngularStack Overflow