简体   繁体   English

单例服务不适用于延迟加载的模块

[英]Singleton services are not available to lazy loaded modules

I recently split my single AppModule into multiple modules and now I am attempting to lazy-load a module and make it use singleton services from a shared module. 我最近将我的单个AppModule为多个模块,现在我正在尝试延迟加载模块并使其使用来自共享模块的单例服务。

I followed the steps mentioned in the docs (as well as in this tutorial ) and created a shared CoreModule that provides singleton services. 我按照文档中提到的步骤(以及本教程 )创建了一个提供单例服务的共享CoreModule However, when one of the shared module's services is trying to inject any of the singleton services, the following exception is thrown: 但是,当其中一个共享模块的服务尝试注入任何单例服务时,将引发以下异常:

EXCEPTION: Uncaught (in promise): Error: No provider for HttpClientService!
Error: No provider for HttpClientService!
    at NoProviderError.BaseError [as constructor] (http://localhost:5000/lib/angular/@angular/core/bundles/core.umd.js:1105:38)

app.module.ts

@NgModule({
    imports: [
        BrowserModule,
        CoreModule.forRoot(),
        AppRoutingModule
    ]
})
export class AppModule { }

app-routing.module.ts

export const routes: Routes = [
    {
        path: "mailgroups",
        loadChildren: "app/mailgroup/mailgroup.module#MailGroupModule"  // <-- lazy loading the module
    }
];

@NgModule({
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ],
})
export class AppRoutingModule { }

core.module.ts (shared module) core.module.ts (共享模块)

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

    static forRoot(): ModuleWithProviders {
        return {
            ngModule: CoreModule,
            providers: [
                HttpClientService,  // <-- singleton service 1
                UserService         // <-- singleton service 2
            ]
        };
    }
}

mailgroup.module.ts (lazy loaded module) mailgroup.module.ts (延迟加载模块)

@NgModule({
    imports: [
        MailGroupRoutingModule
    ]
})
export class MailGroupModule { }

What's interesting, is that when I import the shared module CoreModule to the lazy-loaded module MailGroupModule , I don't get any exception (despite the throw new Error(...) in the constructor), because the parentModule argument is always null . 有趣的是,当我将共享模块CoreModule导入到延迟加载的模块MailGroupModule ,我没有得到任何异常(尽管在构造函数中throw new Error(...) ),因为parentModule参数始终为null

Am I missing something obvious here? 我错过了一些明显的东西吗? (left out declarations that I deemed unnecessary) (遗漏了我认为不必要的声明)

After many hours of programming "at random", while pulling my hair out, my efforts paid off. 经过几个小时的“随机”编程,在拔头发的同时,我的努力得到了回报。 The issue was in a malconfigured system.config.js . 问题出在一个配置错误的system.config.js

When comparing SystemJS configuration to the systemjs.config.web.js used in the docs , I noticed subtle differences in the way the app folder and the path to the file that bootstraps the app are configured in my file. 在将SystemJS配置与文档中使用的systemjs.config.web.js进行比较时,我注意到app文件夹和引导应用程序的文件路径在我的文件中的配置方式存在细微差别。

✘ Before (Malconfigured SystemJS) ✘之前 (Malconfigured SystemJS)

System.config({
    paths: { ... },
    map: {
        app: '/app',                // <-- This line (incorrect)
        ...
    },
    packages: {
        app: {
            main: '/main.js'        // <-- And this line (incorrect)
            defaultExtension: 'js'
        }
    }
})

Notice the leading slash in the app: '/app' and a relative path in main: '/main.js' . 注意app: '/app'的前导斜杠app: '/app'main: '/main.js'的相对路径main: '/main.js'

✔ After (Correct SystemJS configuration) ✔之后 (正确的SystemJS配置)
(changed to app: 'app' and main: './main.js' ) (更改为app: 'app'main: './main.js'

System.config({
    paths: { ... },
    map: {
        app: 'app',                 // <-- This line (correct)
        ...
    },
    packages: {
        app: {
            main: './main.js'       // <-- And this line (correct)
            defaultExtension: 'js'
        }
    }
})

So, these two subtle fixes made all the difference in the world! 所以,这两个微妙的修复使世界变得与众不同!

Now, too, trying to import the shared module CoreModule anywhere else but AppModule , results in an exception being thrown, as expected. 现在,尝试在除AppModule任何其他地方导入共享模块CoreModule ,会导致异常被抛出,如预期的那样。

according to best practice, the CoreModule is an extension to the AppModule. 根据最佳实践,CoreModule是AppModule的扩展。 it shouldn't be a shared module. 它不应该是一个共享模块。 it should only be imported and used by the AppModule a shared module, should be called..... SharedModule 它应该只被AppModule导入并使用一个共享模块,应该被称为..... SharedModule

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

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