typescript - Angular 订阅方法被调用多次
在 Angular 6 上我创建了一个服务
@Injectable({ providedIn: 'root' })
export class CrossEventService {
public refresh$: EventEmitter<string> = new EventEmitter<string>();
public refreshSections(event: any) {
this.refresh$.emit(event)
}
}
现在从另一个组件的 ngOnInit 方法,如果调用了那个特定的方法
像调用方法一样
this.CrossEventService.refreshSections("");
现在我正在检查另一个组件的 ngOnInit 方法
ngOnInit() {
this.CrossEventService.refresh$.subscribe(data => {
if (data) {
// call whatever method i need to call from my current component
}
});
但是在某些地方,上述订阅方法被调用了多次?
答案#1
在服务中避免使用 EventEmitter:
我不确定你的目标是什么,但在 服务 中使用 EventEmitter 是一种 不推荐的做法。根据 Angular 文档,EventEmitter 应该与 @Output 装饰器一起使用,而 @Output 装饰器对服务没有任何作用(它用于子组件向父组件通信)。另一方面,这也会迫使你暴露你的发射器。
@Injectable()
export class MyService {
@Output() // <<< has no effect
public events: EventEmitter<any> = new EventEmitter();
// ^^ makes the emitter public
}
相反,更倾向于使用 Subject 或 BehaviorSubject 方法:
正如 @Mark Rajcok 在另一篇帖子中建议的,优先使用以下任一方法:
Subject 既是一个可观察对象(因此我们可以对它进行 subscribe()),又是一个观察者(因此我们可以调用 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)
}
}
如果你想知道为什么要创建一个 refreshStream$,它以 _refreshSource$作为源,那是因为当我们希望从 subject 暴露数据的同时,又想防止新的数据被推回到 subject 中时,这很有用。
所以这就是为什么你需要像从组件中那样触发 refreshSections 的原因:
this.CrossEventService.refreshSections("");
但是然后订阅 refreshStream$。请记住,所有订阅 refreshStream 的组件都会被激活,并传入 subject 的新值:
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 语法。
