【问题标题】:Angular 2 - multiple instance of service createdAngular 2 - 创建了多个服务实例
【发布时间】:2023-03-25 19:41:01
【问题描述】:

我创建了 AngularJS 2 服务并在 2 个不同的组件中使用它:App-Component 和 Sub-Component。我的服务的每个输出属性“日志”(一个字符串)。

StateService 类:

@Injectable ()
class StateService {

    public log : string;
    static count : number = 0;

    constructor () {
        this.log = '';
        StateService.count++;
        this.writeToLog ('CREATED '+StateService.count+' at ' + new Date().toString());
    }

    public writeToLog (text : string) : void {
        this.log += text + '\n';
    }
}  

组件:

@Component ({
    selector : 'Sub-Component',
    template : `<hr>
            This is the Sub-Component !
            <BR>
            StateService Log : 
            <pre>{{ _stateService.log }}</pre>
            <button (click)="WriteToLog ()">Write to log</button>
            `,
    providers : [StateService]
})

export class SubComponent {
    constructor (private _stateService : StateService) {
    }

    public WriteToLog () : void {
        this._stateService.writeToLog ('From Sub-Component - This is '+new Date().toString());
    }
}

代码here现场示例

我除了服务创建一次,当每个组件调用WriteToLog方法时,每个组件的输出都是一样的,但事实并非如此。

输出示例:

App-Component 可以输出这个:

实例 1 - 创建于 2016 年 1 月 21 日星期四 11:43:51

来自 App-Component - 这是 2016 年 1 月 21 日星期四 11:43:54

来自 App-Component - 这是 2016 年 1 月 21 日星期四 11:43:55

子组件可以输出这个:

实例 2 - 创建于 2016 年 1 月 21 日星期四 11:43:51

来自子组件 - 这是 2016 年 1 月 21 日星期四 11:43:57

来自子组件 - 这是 2016 年 1 月 21 日星期四 11:43:58

看来创建了 2 个服务实例(实例 1 + 实例 2)

我只想要一个实例;)当我在日志中附加字符串时,它必须出现在两个组件中。

感谢您的帮助

【问题讨论】:

  • 仅供参考,Angular 2 不称为 AngularJS 2。

标签: angular angular2-services


【解决方案1】:

更新 Angular >= 2.0.0-RC.6

不要将服务添加到组件的提供者。 而是将其添加到

@NgModule({ providers: [...], ...

(对于一个延迟加载的模块,因为延迟加载的模块引入了它们自己的作用域)

@Component ({
    selector : 'Sub-Component',
    template : `<hr>
            This is the Sub-Component !
            <BR>
            StateService Log : 
            <pre>{{ _stateService.log }}</pre>
            <button (click)="WriteToLog ()">Write to log</button>
            `,
    // providers : [StateService] <== remove
})

角度

如果你将它添加到一个组件上,你会为每个组件实例获得一个新的服务实例。而是将其添加到

bootstrap(AppComponent, [StateService]);

您可以通过将其添加到单个组件来获得更细粒度的控制,然后该组件和所有子组件都会注入相同的实例,否则应用程序将使用由bootstrap() 创建的实例。这是 Angulars DI 中的“分层”。

另请参阅
- http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html
- http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

【讨论】:

  • +1 我找到了here - 但不清楚这是我应该调用服务的地方。还 - 未经测试 - 它在哪里说每个被注入服务的组件 - 将创建一个新实例?
  • 好问题。我没有看到文档中明确提到它,但是有很多文档,我还没有全部阅读。我是从 AngularDart 1.0 开发过程中的讨论中了解到的。 DI 为每个提供者维护一个实例。每个提供者实例都指向一个服务实例。这就是为什么如果您在多次添加到应用程序的组件上提供服务时会获得多个实例。对于全局添加的提供程序(AppComponent、NgModule),将永远只有一个实例。
  • @GünterZöchbauer 我已经尝试过使用最新的 Angular 版本,但我找不到放置它的地方,所以它可以运行一次(见控制台)plnkr.co/edit/LvO6yVOQjKoCVogK7HRh?p=preview
  • 如果您在AppModule 中提供它(并且只有在那里),那么它是单身人士最安全的地方。您也可以在导入的@NgModule() 中提供它,但如果它是延迟加载的模块,您必须在此处采取特殊预防措施。 plnkr.co/edit/JYZrPMvIdrtMtbltbMIz?p=preview
  • 如果您想要整个应用程序的单个实例,请将其放入 @NgModule(...)。如果您希望每个组件实例(及其子实例)有一个实例,并且该服务在组件之外不可用,则将其放在 @Component(...)
【解决方案2】:

除了 Günter 的出色回答之外,此链接也许可以提供有关 Angular2 的分层依赖注入如何工作的更多详细信息:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    • 2016-07-11
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多