我有两个函数,一个返回observableA
,另一个返回observableB
。我希望getter和observableB
的订阅都延迟到observableA
完成为止(但是当我订阅observableB
,{{1}时也可能是这种情况}已经完成)。
我已经尝试使用observableA
和pipe
,但是很遗憾,这只会阻止执行,并且如果skipUntil
尚未完成,也不会延迟执行。
observableA
找到一种非常类似于RxJS的方式会很棒:)
更新1:functionA() {
this.observableA$ = getObservableA()
this.observableA$.subscribe(_ => {
// A: This line should execute *before* line B
})
}
functionB() {
this.observableB$ = getObservableB() // This getter should execute *after* line A
this.observableB$.subscribe(_ => {
// B: This line should execute *after* line A
})
}
// Two functions are called independently
functionA()
functionB()
的问题:
如前所述,两个函数都被独立调用,当像建议的那样使用concat
时,将导致observableA$
的双重执行。此外,concat
中的订阅将被执行两次,我不希望执行。
functionB
更新2:@Wilhelm Olejnik通过使用其他functionA() {
this.observableA$ = getObservableA()
this.observableA$.subscribe(_ => {
// A: This line should execute *before* line B
})
}
functionB() {
Observable.concat(
this.observableA$, // I get executed once again :(
Observable.defer(() => getObservableB()) // To prevent earlier execution
).subscribe(() => {
// B: This line should execute *after* line A
console.log("I'm logged twice, once for each observable :(")
})
}
// Two functions are called independently
functionA()
functionB()
答案 0 :(得分:1)
我遇到了类似的情况,我创建了一个服务SyncService
以同步可观察对象。对我来说,ObsA
和ObsB
来自不同的组件。 ComponentA
加载了自己的数据后,得到了ComponentB
所需的一些初始化数据。
在ComponentA
中,我订阅了ObsA
(从getInitData()
返回)并调用了同步服务:
public initialize() {
this.apiSvc.getInitData().subscribe((initData) => {
this.data = initData;
this.syncService.setA(initData);
}
}
然后,在ComponentB
中,我订阅ObsB
(从getBData()
返回),然后订阅同步服务:
public loadBData() {
this.apiSvc.getBData().subscribe((dataB) => {
this.syncService.setB(dataB).subscribe((dataA, dataB) => {
this.doStuffWithAAndB(dataA, dataB);
}
}
}
最后,同步服务如下所示:
@Injectable
export class SyncService {
private dataA: DataA = null;
private dataB: DataB = null;
private gotAEvent: new EventEmitter<DataA>();
public setA(dataA: DataA) {
this.dataA = dataA;
if (this.dataB != null) {
// ObsB was already resolved!
this.gotAEvent.emit(dataA);
}
}
public setB(dataB: DataB) {
this.dataB = dataB;
if (this.dataA != null) {
return of({this.dataA, this.dataB});
} else {
return this.gotAEvent().map((dataA: DataA) => {
return {dataA, dataB};
}
}
}
}
答案 1 :(得分:1)
如果我正确理解了所有内容,则希望延迟执行getObservableB
,直到将一些可观察到的属性分配给属性observableA$
。
也许可以通过一些Proxy
技巧来实现,但是我认为将observableA$
更改为空初始化的BehaviorSubject
会更容易。然后您可以观察observableA$
并在发出非空信号时创建observableB$
。
https://stackblitz.com/edit/rxjs-mm2edy
import { of, BehaviorSubject, timer } from 'rxjs';
import { filter, switchMap, mapTo, tap } from 'rxjs/operators';
const getObservableA = () => timer(100).pipe(
tap(() => console.log('getObservableA')),
mapTo('A')
);
const getObservableB = () => timer(100).pipe(
tap(() => console.log('getObservableB')),
mapTo('B')
);
class Test {
// init observableA$ as BehaviorSubject with null state
observableA$ = new BehaviorSubject(null);
observableB$;
functionA() {
getObservableA().subscribe(val => {
console.log(val)
this.observableA$.next(val); // notify subscribers that observableA$ is ready
});
}
functionB() {
this.observableB$ = this.observableA$.pipe(
filter(value => value !== null), // ignore observableA$ until initalized
switchMap(value => getObservableB())
)
this.observableB$.subscribe(console.log)
}
}
const test = new Test();
test.functionB();
setTimeout(() => test.functionA(), 500);
// getObservableA
// A
// getObservableB
// B