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

查看:73
本文介绍了使用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.

如果单击模块1页面1"和模块2页面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正在使用loadChildren Mode2Module正在使用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-为什么不好

如果SharedModule为延迟加载的服务提供服务,为什么会很糟糕 模块?
当我们 讨论了使提供程序脱离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和 ContactModule.

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

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

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的新实例. 这是与应用程序范围完全不同的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天全站免登陆