我需要将两个来源的数据合并为一个res: {data1: any, data2: any}
对象,并且即使其中一个来源没有发出任何值,我也需要实现这一目标
这是我期望的结构:
xxx (
source1,
source2,
(data1, data2) => ({data1: data1, data2: data2})
).subscribe(res => {
doSomething1(res.data1)
doSomething2(res.data2)
})
有没有可以执行此操作的rxjs运算符?
目前,我可以使用startWith
和combineLatest
的组合来解决此问题-我发出了空值,因此combineLatest
可以开始发出值-没有startWith(null)
的任何更好的解决方法?
combineLatest (
source1.pipe(startWith(null)),
source2.pipe(startWith(null)),
(data1, data2) => ({data1: data1, data2: data2})
).subscribe(res => {
if(res.data1) {
doSomething1(res.data1)
}
if(res.data2) {
doSomething2(res.data2)
}
})
答案 0 :(得分:1)
您可以使用BehaviorSubject。如果没有更多的最新值(在这种情况下为null),这将为您提供一个在订阅时会发出默认值的流。
const subject1 = new BehaviorSubject(null),
subject2 = new BehaviorSubject(null);
source1.subscribe(subject1);
source2.subscribe(subject2);
combineLatest(subject1, subject2).subscribe(res => {
if(res.data1) {
doSomething1(res.data1)
}
if(res.data2) {
doSomething2(res.data2)
}
});
答案 1 :(得分:1)
我知道这是一个旧线程。然而,我最近遇到了同样的问题并像@godblessstrawberry 一样解决了
const source1 = new Subject(),
source2 = new Subject();
const vm$ = combineLatest([
source1.pipe(startWith([{id: 1}])),
source2.pipe(startWith(['abc'])),
])
.pipe(map(([profile, page]) => ({profile, page})));
vm$.subscribe(stream => {
console.log({stream});
})
答案 2 :(得分:0)
如@ritaj所述,您似乎已经做好了,尽管:
startWith
。这是一个大理石图,用于比较两种方法: * 请注意,带有startWith
的流发出两次
使用唯一对象(或符号)代替简单的null
,以防万一源流确实发出null
。这将确保我们仅过滤掉标记,而不是真实结果
在订阅中使用过滤器代替if-else
-应该看起来更干净一些。这是保持.subscribe
越薄越好的普遍做法,
这里有个例子:
const NO_VALUE = {};
const result$ = combineLatest(
a$.pipe( defaultIfEmpty(NO_VALUE) ),
b$.pipe( defaultIfEmpty(NO_VALUE) )
)
.pipe(filter(([a, b]) => a !== NO_VALUE || b !== NO_VALUE))
^ Run this code with a marble diagram 。
希望这会有所帮助