使用 loadChildren 延迟加载 angular2 路由器的服务不是单例的 [英] Service is not being singleton for angular2 router lazy loading with loadChildren

查看:32
本文介绍了使用 loadChildren 延迟加载 angular2 路由器的服务不是单例的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是普鲁克.https://plnkr.co/edit/tsNlmRth4mRzz0svGWLK?p=preview

我在其中创建了两个模块,每个模块有两个组件和一个服务.我希望服务应该是模块级别的单例(保存状态).

In which I have created two module with two components and one service each. I want the service should be singleton (save state) in the module level.

如果您点击Module 1 Page 1"和Module 2 Page 2",它将显示两个不同的随机数.当我在构造函数中生成这个数字时.因此,每次页面更改时都会创建该服务.但是 module2 表现得很好.

If you click on 'Module 1 Page 1' and 'Module 2 Page 2' It will display two different random numbers. As I am generating this number in constructor. So the service is being created each time page change. But module2 is behaving perfectly.

注意:Mode1Module 正在使用 loadChildrenMode2Module 正在使用 children

Note: Mode1Module is using loadChildren Mode2Module is using children

我发现根据此 angular2 rc5 路由器服务单例,早先已修复了相同类型的问题

但我认为它仍然存在.所以请帮我解决这个问题.

But I think still it is there. So please help me to solve this out.

推荐答案

延迟加载的模块有自己的根作用域.添加到延迟加载模块的提供程序在该根范围而不是应用程序的根范围中获得一个实例.如果将提供程序添加到非延迟加载的模块,则只会在应用程序根范围内创建单个实例.

Lazy loaded modules have their own root scope. Providers added to lazy loaded modules get an instance in that root scope instead of the root scope of the application. If you add the provider to a module that is not lazy loaded, only a single instance at the application root scope will be created.

https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-lazy-loaded-module-provider-visibility

为什么在延迟加载的模块中提供的服务仅对其可见模块?
与启动时加载的模块的提供者不同,延迟加载的模块是模块范围的.

Why is a service provided in a lazy loaded module visible only to that module?
Unlike providers of the modules loaded at launch, providers of lazy loaded modules are module-scoped.

当 Angular 路由器延迟加载一个模块时,它会创建一个新的执行上下文.该上下文有自己的注入器,它是一个直接应用程序注入器的子级.

When the Angular router lazy-loads a module, it creates a new execution context. That context has its own injector which is a direct child of the application injector.

路由器添加惰性模块的提供者和它的提供者导入模块到这个子注入器.

The router adds the lazy module's providers and the providers of its imported modules to this child injector.

这些提供程序不受应用程序提供程序更改的影响具有相同的查找标记.当路由器在其中创建一个组件时延迟加载的上下文,Angular 更喜欢创建的服务实例从这些提供者到应用程序根的服务实例喷油器.

These providers are insulated from changes to application providers with the same lookup token. When the router creates a component within the lazy loaded context, Angular prefers service instances created from these providers to the service instances of the application root injector.

https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-why-bad

如果 SharedModule 为延迟加载提供服务为什么不好?模块?
这个问题出现在 Angular 模块章节中,当我们讨论了将提供者置于 SharedModule 之外的重要性.

Why is it bad if SharedModule provides a service to a lazy loaded module?
This question arose in the Angular Module chapter when we discussed the importance of keeping providers out of the SharedModule.

假设我们已经在模块的提供者中列出了 UserService(其中我们没有).假设每个模块都导入这个 SharedModule(它他们都这样做).

Suppose we had listed the UserService in the module's providers (which we did not). Suppose every module imports this SharedModule (which they all do).

当应用启动时,Angular 会急切地加载 AppModule 和联系模块.

When the app starts, Angular eagerly loads the AppModule and the ContactModule.

导入的 SharedModule 的两个实例都将提供用户服务.Angular 在根应用注入器中注册了其中之一(看上面).然后某个组件注入了 UserService,Angular 找到了在应用程序根注入器中,并提供应用程序范围的单例用户服务.没问题.

Both instances of the imported SharedModule would provide the UserService. Angular registers one of them in the root app injector (see above). Then some component injects UserService, Angular finds it in the app root injector, and delivers the app-wide singleton UserService. No problem.

现在考虑延迟加载的 HeroModule!

Now consider the HeroModule which is lazy loaded!

当路由器延迟加载 HeroModule 时,它​​会创建一个子注入器并使用该子注入器注册 UserService 提供者.这子注入器不是根注入器.

When the router lazy loads the HeroModule, it creates a child injector and registers the UserService provider with that child injector. The child injector is not the root injector.

当 Angular 创建一个惰性 HeroComponent 时,它必须注入一个用户服务.这次它在懒惰中找到了一个 UserService 提供者模块的子注入器并创建 UserService 的新实例.这是一个与应用程序范围内完全不同的 UserService 实例Angular 注入其中一个急切加载的单例版本组件.

When Angular creates a lazy HeroComponent, it must inject a UserService. This time it finds a UserService provider in the lazy module's child injector and creates a new instance of the UserService. This is an entirely different UserService instance than the app-wide singleton version that Angular injected in one of the eagerly loaded components.

这几乎肯定是一个错误.

That's almost certainly a mistake.

证明给自己看.运行实时示例.修改 SharedModule以便它提供 UserService 而不是 CoreModule.然后在联系人"和英雄"链接之间切换几次.这用户名变得疯狂,因为 Angular 创建了一个新的 UserService每次都实例.

Prove it for yourself. Run the live example. Modify the SharedModule so that it provides the UserService rather than the CoreModule. Then toggle between the "Contact" and "Heroes" links a few times. The username goes bonkers as the Angular creates a new UserService instance each time.

https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-why-child-injector

为什么延迟加载会创建子注入器?
角添加@NgModule.providers 到应用程序根注入器......除非模块是延迟加载的.然后它创建一个子注入器并添加子注入器的模块提供者.

Why does lazy loading create a child injector?
Angular adds @NgModule.providers to the application root injector ... unless the module is lazy loaded. Then it creates a child injector and adds the module's providers to the child injector.

这意味着一个模块的行为取决于它是否在应用程序启动期间加载或稍后延迟加载.忽视这种差异会导致不良后果.

This means that a module behaves differently depending on whether it is loaded during application start or lazy loaded later. Neglecting that difference can lead to adverse consequences.

为什么 Angular 不向应用根注入器添加延迟加载的提供程序就像急切加载的模块一样?为什么不一致?

Why doesn't Angular add lazy loaded providers to the app root injector as it does for eagerly loaded modules? Why the inconsistency?

答案基于 Angular 的一个基本特征依赖注入系统.注入器可以添加提供者,直到它第一次使用.一旦注入器开始创建和交付服务,它的提供者列表被冻结.不允许新的提供者.

The answer is grounded in a fundamental characteristic of the Angular dependency injection system. An injector can add providers until it is first used. Once an injector starts creating and delivering services, its provider list is frozen. No new providers allowed.

当一个应用程序启动时,Angular 首先配置根与之前所有急切加载的模块的提供者的注入器创建它的第一个组件并注入任何提供的服务.应用程序启动后,应用程序根注入器将关闭到新的提供商.

When an applications starts, Angular first configures the root injector with the providers of all eagerly loaded modules before creating its first component and injecting any of the provided services. Once the application begins, the app root injector is closed to new providers.

时间过去了.应用程序逻辑触发模块的延迟加载.Angular 必须将延迟加载模块的提供者添加到注入器某处.它无法将它们添加到应用程序根注入器中,因为注入器对新提供者关闭.所以 Angular 创建了一个新的孩子延迟加载模块上下文的注入器.

Time passes. Application logic triggers lazy loading of a module. Angular must add the lazy loaded module's providers to an injector somewhere. It can't added them to the app root injector because that injector is closed to new providers. So Angular creates a new child injector for the lazy loaded module context.

这篇关于使用 loadChildren 延迟加载 angular2 路由器的服务不是单例的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆