简体   繁体   English

EventEmitter的发送方法不向订阅者发送值

[英]Emit method of EventEmitter not emitting values to subscribers

So I am trying to connect two components through a service, LoaderComponent and AppComponent with LoaderService , so that when app fetches data a loader shows up. 因此,我试图通过服务将两个组件( LoaderComponentAppComponentLoaderService ,以便在应用程序获取数据时显示一个加载器。 But when I try to use an EventEmitter to emit changes to the components they don't get the changes but when the service subscribes to itself, it can get the changes 但是,当我尝试使用EventEmitter向组件发出更改时,它们没有得到更改,但是当服务订阅自身时,它可以获取更改

LoaderService.ts LoaderService.ts

import { EventEmitter, Injectable } from '@angular/core';

@Injectable()

class LoaderService {
  @Output change: EventEmitter<number> = new EventEmitter<number>();
  private state: number = 0;

  constructor() { 
     this.change.subscribe(state => console.log(state)); 
     this.setState(1) 
  }

  setState(state: number) {
     this.state = state;
     this.change.emit(this.state);
  }
}
// Shows state when  but outside of the service event is not detected, also tried EventEmitter from from events

I expect to get events from the LoaderService to subscribers 我希望从LoaderService到订阅者获取事件

First thing, EventEmitters and Outputs don't belong in a service. 首先, EventEmitters和Outputs不属于服务。

I will refactor to use subjects and also protect your subject by making it private and exposing a public observable, this limits how your subject state can be modified, this is not required but is generally considered good practice: 我将重构使用主题,并通过将其设置为私有并公开可见的方式来保护您的主题,这限制了如何修改您的主题状态,这不是必需的,但通常被认为是好的做法:

import { Injectable } from '@angular/core';
import {Subject} from 'rxjs/Subject';
import {Observable} from 'rxjs/Observable';

@Injectable()

class LoaderService {
  private change: Subject<number> = new Subject<number>();
  change$: Observable<number> = this.change.asObservable();
  private state: number = 0;

  constructor() { 
     this.change$.subscribe(state => console.log(state)); 
     this.setState(1) 
  }

  setState(state: number) {
     this.state = state;
     this.change.next(this.state);
  }
}

Second, this is likely an issue with how you provide your service. 其次,这可能与您提供服务的方式有关。 If you have an app component template like: 如果您有类似以下内容的应用程序组件模板:

<loader-component></loader-component>
<loader-component></loader-component>

with 2 loader components side by side, and the loader component has a providers array like: 具有2个并排的loader组件,并且loader组件具有一个provider数组,例如:

providers: [LoaderService]

then these 2 loaders are receiving different copies of the same service as they each provide and inject their own, so they will not see each other's events. 则这两个加载器将接收各自提供的同一服务的不同副本,并注入自己的副本,因此它们将不会看到彼此的事件。

To remedy this, you provide instead in the app component (and not in the loader component) so they have the same copy of the service, because then the parent is providing the service that each of them inject. 为了解决这个问题,您可以在app组件中提供(而不是在loader组件中),以使它们具有相同的服务副本,因为父级将提供它们每个注入的服务。 If you were to provide in both app component and loader component, they would all receive a different copy. 如果要同时提供应用程序组件和加载器组件,则它们都将收到不同的副本。

If you provide at root (module level) then every component that injects the service (and doesn't provide it's own) will receive the same copy of that service. 如果您在根目录(模块级别)提供,则每个注入服务的组件(不提供它自己的组件)将收到该服务的相同副本。

The appropriate place to provide a service is dependent on your app's needs and the function of the particular service. 提供服务的适当位置取决于您的应用程序的需求和特定服务的功能。

You need to use LoaderService in some component for angular to create it, if we do not use the service any where angular will automatically discard it. 您需要在某个组件中使用LoaderService来创建angular,如果我们不使用该服务,则angular会自动将其丢弃。 Inject LoaderService in app component like below: 在应用程序组件中注入LoaderService ,如下所示:

constructor(private _loadService: LoaderService) {} and then you will see the console.log() . constructor(private _loadService: LoaderService) {} ,然后您将看到console.log()

Also, it is recommended to use either Subject or Behavior Subject from Rxjs instead of Output in a service. 另外,建议在服务中使用Rxjs中的Subject或Behavior Subject,而不是Output。

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

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