简体   繁体   English

如何在我的 .forRoot() 中以 angular 初始化第 3 方模块

[英]how can I initialize a 3rd party module within my .forRoot() in angular

I am building an internal library for our projects, using Angular 6+.我正在为我们的项目构建一个内部库,使用 Angular 6+。 I am using the .forRoot() approach to register global services as documented.我正在使用.forRoot()方法按照文档注册全局服务。

My library will be using ngx-toastr to provide notifications.我的图书馆将使用ngx-toastr来提供通知。 As I don't want each project to deal directly with all the options of ngx-toastr , I am abstracting most of it behind a notifications service.由于我不希望每个项目都直接处理ngx-toastr所有选项, ngx-toastr我将其中的大部分抽象为notifications服务。

The way ngx-toastr works, you can set global options by passing those global options to ToastrModule.forRoot() . ngx-toastr工作方式是,您可以通过将这些全局选项传递给ToastrModule.forRoot()来设置全局选项。

how can I configure ToastrModule as part of my own forRoot() ?如何将ToastrModule配置为我自己的forRoot()

It's clearly a bad idea to add any code inside the .forRoot() , but is the right way to initialize it directly in my @NgModule() ?.forRoot()添加任何代码显然是一个坏主意,但是在我的@NgModule()直接初始化它是正确的方法吗? like this:像这样:

@NgModule({
    imports: [ToastrModule.forRoot(/* options go here? */)],
    declarations: [],
    exports: []
})
export class ToolsCoreModule {
    static forRoot(): ModuleWithProviders {
        return {
            ngModule: ToolsCoreModule,
            providers: [],
        };
    }
}

How would this interact if someone on the team decides to also call ToastrModule.forRoot() within their own module initialization?如果团队中的某个人决定在他们自己的模块初始化中也调用ToastrModule.forRoot() ,这将如何交互?

The root module that exports your notifications service via providers should be the only one that uses ToastrModule.forRoot() in an imports declaration.通过providers导出通知服务的根模块应该是唯一一个在imports声明中使用ToastrModule.forRoot()的模块。

The forRoot() call is a convention and not something enforced by the framework. forRoot()调用是一种约定,而不是框架强制执行的操作。 Others shouldn't be calling this when defining their NgModules if it has already been called higher up.其他人在定义他们的 NgModules 时不应该调用它,如果它已经被更高层调用了。

As mentioned in the Angular documentation: 正如 Angular 文档中提到的:

Only call and import a .forRoot() result in the root application module, AppModule .仅在根应用程序模块AppModule调用并导入.forRoot()结果。 Importing it in any other module, particularly in a lazy-loaded module, is contrary to the intent and will likely produce a runtime error.在任何其他模块中导入它,特别是在延迟加载的模块中,与意图相反,并且可能会产生运行时错误。

... ...

forRoot() and forChild() are conventional names for methods that configure services in root and feature modules respectively. forRoot()forChild()是分别在根和功能模块中配置服务的方法的常规名称。

If your global configuration for ToastrModule never changes, I don't think there's anything wrong doing it the way you've questioned in your snippet.如果您对ToastrModule的全局配置从未改变,我认为按照您在代码片段中提出的问题的方式没有任何问题。

However, if the configuration might change depending on consumers of ToolsCoreModule , you shouldn't be calling forRoot() for each different configuration, as that's wrong by convention.但是,如果配置可能会根据ToolsCoreModule使用者而发生变化,那么您不应该为每个不同的配置调用forRoot() ,因为按照惯例,这是错误的。 In this case, you could consider creating wrappers around the third argument of toast calls to pass common configuration (eg this.toastrService.error(msg, title, config) ).在这种情况下,您可以考虑围绕 toast 调用的第三个参数创建包装器以传递通用配置(例如this.toastrService.error(msg, title, config) )。

As @migh mentioned, forRoot() should only be called by AppModule , but a nested forRoot() within a forRoot() provider is still called by the AppModule , isn't it?正如@migh 所提到的, forRoot()应该只由AppModule ,但是在forRoot()提供者中嵌套的forRoot()仍然由AppModule ,不是吗?

So you can do the following所以你可以执行以下操作

@NgModule({
    imports: [],
    declarations: [],
    exports: [ToastrModule]
})
export class ToolsCoreModule {
    static forRoot(/* your options */): ModuleWithProviders {
        return {
            ngModule: ToolsCoreModule,
            providers: [...ToastrModule.forRoot(/* toastr options */).providers],
        };
    }
}

How would this interact if someone on the team decides to also call ToastrModule.forRoot() within their own module initialization?如果团队中的某个人决定在他们自己的模块初始化中也调用ToastrModule.forRoot() ,这将如何交互?

You'll may get a runtime error or a strange behavior.您可能会收到运行时错误或奇怪的行为。

To avoid the 'strange behavior', you should also add this pattern to your module that prevents double registration:为了避免“奇怪的行为”,您还应该将此模式添加到防止双重注册的模块中:

constructor(@Optional() @SkipSelf() parentModule?: ToolsCoreModule)
{
    if (parentModule)
    {
        throw new Error(
            "ToolsCoreModule is already loaded. Import it in the AppModule only!");
    }
}

That pattern is from the official documentation: https://angular.io/guide/singleton-services#prevent-reimport-of-the-greetingmodule该模式来自官方文档: https : //angular.io/guide/singleton-services#prevent-reimport-of-the-greetingmodule

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM