【问题标题】:Angular subscribe method is calling multiple timeAngular subscribe 方法多次调用
【发布时间】:2020-11-25 22:00:10
【问题描述】:

在 Angular 6 上,我创建了一项服务

@Injectable({ providedIn: 'root' })
export class CrossEventService {
  public refresh$: EventEmitter<string> = new EventEmitter<string>();
  public refreshSections(event: any) {
    this.refresh$.emit(event)
  }
}

如果调用该特定方法,则现在从其他组件 ngOnint 方法

调用方法如

this.CrossEventService.refreshSections(""); 

现在我正在检查其他组件的 ngOnInit 方法

 ngOnInit() {
    this.CrossEventService.refresh$.subscribe(data => {
      if (data) {
        // call whatever method i need to call from my current component
      }
    });

但是在某些地方上面的订阅方法被调用了多次?

【问题讨论】:

  • 它在哪里被多次调用?你能在 plunker 中复制吗?
  • 如果您通过属性绑定或插值在模板中使用this.CrossEventService.refreshSections(""),并且如果您使用默认更改检测策略,则可能会在每个CD 循环中触发它。这反过来会向订阅发出通知。

标签: angular typescript


【解决方案1】:

在服务中避免 EventEmitter:

我不确定您的目标是什么,但在 服务 中使用 EventEmitter 是一种不鼓励的做法。根据 Angular 文档,EventEmitter 应该与对服务没有影响的 @Output 装饰器一起使用(它用于子组件与父组件的通信)。另一方面,它会迫使您暴露发射器。

@Injectable()
export class MyService {
   @Output()   // <<< has no effect
   public events: EventEmitter<any> = new EventEmitter();
   // ^^ makes the emitter public
}

更喜欢 Subject 或 BehaviorSubject 方法:

正如@Mark Rajcok 在另一个post 中所建议的,首选以下任何一种方法:

Subject 既是 Observable(因此我们可以 subscribe() 访问它)又是 Observer(因此我们可以在其上调用 next() 以发出新值)。我们利用此功能。 Subject 允许将值多播到许多观察者。我们不利用此功能(我们只有一个观察者)。

BehaviorSubject 是 Subject 的变体。它具有“当前值”的概念。我们利用这一点:每当我们创建一个 ObservingComponent 时,它都会自动从 BehaviorSubject 获取当前导航项的值。

在您的情况下,服务如下所示:

@Injectable({ providedIn: 'root' })
export class CrossEventService {
  private _refreshSource$ = new Subject<any>();
  public refreshStream$ = this._refreshSource$.asObservable();
  public refreshSections(event: any) {
    this._refreshSource$.next(event)
  }
}

如果你想知道为什么要创建一个以 _refreshSource$ 为源的 refreshStream$,这是因为它在我们希望公开来自主题的数据但同时防止将新数据推回主题时很有用。

这就是为什么您需要像从组件中那样触发 refreshSections:

this.CrossEventService.refreshSections(""); 

然后订阅refreshStream$。请记住,订阅 refreshStream 的所有组件都将被激活并传入主题的新值:

import {Subscription} from 'rxjs/Subscription';

export class ObservingComponent {
  subscription: Subscription;
  event: any;
  constructor(private _crossEventService:CrossEventService) {}
  ngOnInit() {
    this.subscription = this._crossEventService.refreshStream$
       .subscribe(event => this.event = event)
  }
  ngOnDestroy() {
    // prevent memory leak when component is destroyed
    this.subscription.unsubscribe();
  }
}

请注意,我添加了来自 RxJs 的订阅,以便在组件被销毁时取消订阅主题。还要清楚地知道要传递给.next({information}) 的信息,因为您可以跳过从EventEmitter 继承的event 语法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 2016-10-07
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    相关资源
    最近更新 更多