Angular: 当多个订阅(BehaviorSubjects)都定义时调用方法
Angular: Invoke method when multiple subscriptions (BehaviorSubjects) are all defined
我已经设置了一个 "global" 服务,以便在我的 Angular 应用程序中跨组件共享参数:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class ParameterService {
param1 = new BehaviorSubject(null);
publishParam1(data: number) {
this.param1.next(data);
}
param2 = new BehaviorSubject(null);
publishParam2(data: number) {
this.param2.next(data);
}
}
需要其中一个或两个参数的组件可以订阅,并在这些参数发生变化时收到通知:
private subscriptions: Array<Subscription> = [];
param1: number; // keep local copies of the params
param2: number;
ngOnInit(): void {
this.subscriptions.push(this._parameterService.param1.subscribe(
data => {
console.log("param1 changed: " + data);
if (data != null) {
this.param1 = data;
// NB! this.param2 may be undefined!
this.getDataFromAPI(this.param1, this.param2);
}
}
));
this.subscriptions.push(this._parameterService.param2.subscribe(
data => {
console.log("param2 changed: " + data);
if (data != null) {
this.param2 = data;
// NB! this.param1 may be undefined!
this.getDataFromAPI(this.param1, this.param2);
}
}
));
}
ngOnDestroy() {
//
this.subscriptions.forEach((subscription: Subscription) => {
subscription.unsubscribe();
});
}
param1
和 param2
由 AppComponent
异步初始化,因此订阅 both 参数的组件将是 "notified"(接收值)以任意顺序。 getDataFromAPI
应该在任何一个参数更改时获取新数据,因此两个订阅都会调用该方法,但另一个参数可能仍然是 undefined
.
显然,只需在调用 getDataFromAPI
之前检查是否定义了其他参数,即可轻松解决此问题,但我想知道处理这种(当然常见)情况的最佳方法是什么? 我应该使用 promises 还是 await 来确保 getDataFromAPI
仅在定义了两个(所有)参数时才被调用?
想到的一个简单想法是确保 ParameterService
只包含一个参数;即,将 param1
和 param2
包装在一些 "state class":
中
export class StateObject {
param1: number;
param2: number;
constructor() { }
}
这样 ParameterService
就变成了,
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { StateObject } from './stateobject';
@Injectable()
export class ParameterService {
state = new BehaviorSubject(null);
publishState(data: StateObject) {
this.state.next(data);
}
}
你可以试试:
let subscription = Rx.Observable.combineLatest(
this._parameterService.param1,
this._parameterService.param2
)
.subscribe(data => {
console.log("param1 or param2 changed: " + data);
let [p1, p2] = data;
this.getDataFromAPI(this.param1 = p1, this.param2 = p1);
})
);
或带投影功能:
let subscription = Rx.Observable.combineLatest(
this._parameterService.param1,
this._parameterService.param2,
(p1, p2) => { p1: p1, p2: p2 }
)
.subscribe(data => {
console.log("param1 or param2 changed: " + data);
this.getDataFromAPI(this.param1 = data.p1, this.param2 = data.p2);
})
);
我已经设置了一个 "global" 服务,以便在我的 Angular 应用程序中跨组件共享参数:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class ParameterService {
param1 = new BehaviorSubject(null);
publishParam1(data: number) {
this.param1.next(data);
}
param2 = new BehaviorSubject(null);
publishParam2(data: number) {
this.param2.next(data);
}
}
需要其中一个或两个参数的组件可以订阅,并在这些参数发生变化时收到通知:
private subscriptions: Array<Subscription> = [];
param1: number; // keep local copies of the params
param2: number;
ngOnInit(): void {
this.subscriptions.push(this._parameterService.param1.subscribe(
data => {
console.log("param1 changed: " + data);
if (data != null) {
this.param1 = data;
// NB! this.param2 may be undefined!
this.getDataFromAPI(this.param1, this.param2);
}
}
));
this.subscriptions.push(this._parameterService.param2.subscribe(
data => {
console.log("param2 changed: " + data);
if (data != null) {
this.param2 = data;
// NB! this.param1 may be undefined!
this.getDataFromAPI(this.param1, this.param2);
}
}
));
}
ngOnDestroy() {
//
this.subscriptions.forEach((subscription: Subscription) => {
subscription.unsubscribe();
});
}
param1
和 param2
由 AppComponent
异步初始化,因此订阅 both 参数的组件将是 "notified"(接收值)以任意顺序。 getDataFromAPI
应该在任何一个参数更改时获取新数据,因此两个订阅都会调用该方法,但另一个参数可能仍然是 undefined
.
显然,只需在调用 getDataFromAPI
之前检查是否定义了其他参数,即可轻松解决此问题,但我想知道处理这种(当然常见)情况的最佳方法是什么? 我应该使用 promises 还是 await 来确保 getDataFromAPI
仅在定义了两个(所有)参数时才被调用?
想到的一个简单想法是确保 ParameterService
只包含一个参数;即,将 param1
和 param2
包装在一些 "state class":
export class StateObject {
param1: number;
param2: number;
constructor() { }
}
这样 ParameterService
就变成了,
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { StateObject } from './stateobject';
@Injectable()
export class ParameterService {
state = new BehaviorSubject(null);
publishState(data: StateObject) {
this.state.next(data);
}
}
你可以试试:
let subscription = Rx.Observable.combineLatest(
this._parameterService.param1,
this._parameterService.param2
)
.subscribe(data => {
console.log("param1 or param2 changed: " + data);
let [p1, p2] = data;
this.getDataFromAPI(this.param1 = p1, this.param2 = p1);
})
);
或带投影功能:
let subscription = Rx.Observable.combineLatest(
this._parameterService.param1,
this._parameterService.param2,
(p1, p2) => { p1: p1, p2: p2 }
)
.subscribe(data => {
console.log("param1 or param2 changed: " + data);
this.getDataFromAPI(this.param1 = data.p1, this.param2 = data.p2);
})
);