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

时间:2016-12-07 22:33:17

标签: angular lazy-loading angular2-services

我最近将单个AppModule拆分为多个模块,现在我正在尝试延迟加载模块并使其使用来自共享模块的单例服务。

我按照提及的步骤in the docs(以及in this tutorial)创建了一个提供单例服务的共享CoreModule。但是,当其中一个共享模块的服务尝试注入任何单例服务时,会抛出以下异常:

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 (共享模块)

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 (延迟加载模块)

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

有趣的是,当我将共享模块CoreModule导入到延迟加载模块MailGroupModule时,我没有得到任何异常(尽管构造函数中有throw new Error(...)) ,因为parentModule参数始终为null

我错过了一些明显的东西吗? (遗漏了我认为不必要的声明)

2 个答案:

答案 0 :(得分:2)

经过几个小时的编程&#34;随意&#34;在拔头发的同时,我的努力得到了回报。该问题出现在配置错误的 system.config.js 中。

将SystemJS配置与the systemjs.config.web.js used in the docs进行比较时,我注意到在我的文件中配置app文件夹和引导应用程序的文件路径的方式存在细微差别。

✘之前(错误配置的SystemJS)

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

注意app: '/app'中的前导斜杠和main: '/main.js'中的相对路径。

之后(正确的SystemJS配置)
(已更改为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'
        }
    }
})

所以,这两个微妙的修复使世界变得与众不同!

现在,尝试将共享模块CoreModule导入除AppModule以外的任何其他位置,会导致异常被抛出,如预期的那样。

答案 1 :(得分:1)

根据最佳实践,CoreModule是AppModule的扩展。它不应该是一个共享模块。它只能由AppModule导入和使用 一个共享模块,应该被称为..... SharedModule