【问题标题】:Emit method of EventEmitter not emitting values to subscribersEventEmitter 的 Emit 方法不向订阅者发送值
【发布时间】:2019-04-30 18:50:36
【问题描述】:

所以我试图通过服务连接两个组件,LoaderComponentAppComponentLoaderService,以便在应用程序获取数据时显示加载程序。但是,当我尝试使用 EventEmitter 向组件发出更改时,他们不会得到更改,但是当服务订阅时 对自己来说,它可以得到改变

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

我希望从LoaderService 向订阅者发送事件

【问题讨论】:

  • 所以this.change.subsribe(state =&gt; console.log(state)); 上的错字与它无关,对吧?另外,输出是@Output()
  • 对不起,打错了,但在文件里没问题
  • t 在这种情况下非常适合设置某种示例.. 工作示例.. 您可以在 Stackblitz 轻松做某事
  • 1.不要在服务上下文中使用事件发射器或输出,使用 rxjs 主题或行为主题,输出和 EventEmitters 专门用于组件事件和模板绑定 2. 如何/在哪里提供此服务?查看此链接以获取有关第 1 点的更多信息:stackoverflow.com/questions/36076700/…
  • @LibbyLebyane 我会考虑 bryan60 评论.. 但是.. 我在这里看不到任何问题stackblitz example

标签: javascript angular typescript observable angular-event-emitter


【解决方案1】:

你需要在某个组件中使用LoaderService 来创建它,如果我们不使用任何服务,Angular 会自动丢弃它。在应用组件中注入LoaderService,如下所示:

constructor(private _loadService: LoaderService) {} 然后你会看到console.log()

另外,建议使用 Rxjs 中的 Subject 或 Behavior Subject 来代替服务中的 Output。

【讨论】:

  • 谢谢,我不知道服务不使用输出
【解决方案2】:

第一件事,EventEmitters and Outputs don't belong in a service.

我将重构以使用主题,并通过将其设为私有并公开公开可观察对象来保护您的主题,这限制了您的主题状态可以修改的方式,这不是必需的,但通常被认为是好的做法:

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);
  }
}

其次,这可能与您提供服务的方式有关。如果您有一个应用组件模板,例如:

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

并排有 2 个加载器组件,加载器组件有一个提供者数组,如:

providers: [LoaderService]

然后这 2 个加载器接收相同服务的不同副本,因为它们各自提供并注入自己的服务,因此它们不会看到彼此的事件。

为了解决这个问题,您改为在应用程序组件中提供(而不是在加载程序组件中),这样它们就拥有相同的服务副本,因为父级提供了它们每个注入的服务。如果你在 app 组件和 loader 组件中都提供,它们都会收到不同的副本。

如果您在根(模块级别)提供服务,那么注入服务的每个组件(并且不提供自己的服务)都将收到该服务的相同副本。

提供服务的适当位置取决于应用的需求和特定服务的功能。

【讨论】:

  • 非常感谢我删除了OutputEventEmitter 我使用了主题,而不是像你坚持的那样
  • 并且还删除了子组件提供者中 LoaderService 的重复项
猜你喜欢
  • 2015-06-30
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-17
  • 2012-12-14
  • 1970-01-01
  • 2019-12-15
相关资源
最近更新 更多