试图重新实现公司的主要应用,从承诺和命令式风格转换为RxJS和功能风格。并发现自己处于特定的情况。
问题:我们在系统中有一个可以过滤的帖子列表。 所以,我创建了一个非常简单的过滤器组件和一个列表组件,我收到这样的数据:
this.items = this.filterChange
.startWith(this.filterComponent.initialValue);
.debounceTime(400)
.switchMap((data) => this.process(data))
.share();
但是我需要从套接字插入另一个事件来更新列表中的各个元素。我们的process
函数可以理解这两个事件并对它们做出反应,但问题是:
merge(this.filterChange.debounceTime(400), this.socketUpdates)
.startWith(this.filterComponent.initialValue);
.switchMap((data) => this.process(data))
.share();
如果在搜索更改后立即更新,我们会丢失搜索更改结果,在这种情况下该怎么办?
PS:我已经考虑选择combineLatest
+ pariwise
来获得改变后的能力并做出反应。难道没有更优雅的解决方案吗?
答案 0 :(得分:2)
这实际上是RxJS的常见错误,当您使用switchMap
(或者concatMap
)时,您正在使用mergeMap
。
switchMap
对于非副作用的只读请求/消息非常安全。如果你是'尝试通过网络更新记录,并且您关心它的完成顺序和处理结果,您想要使用concatMap
。如果您不关心结果的排序,则应使用mergeMap
。
switchMap
- 在获得新值时取消订阅任何待处理的Observable,从而放弃其响应。mergeMap
- 将立即开始并运行它创建的所有Observable并完成,而不必关心结果在它们合并后返回的顺序。concatMap
- 按顺序一次只运行一个Observable,不删除任何内容。merge(this.filterChange.debounceTime(400), this.socketUpdates)
.startWith(this.filterComponent.initialValue);
.concatMap((data) => this.process(data))
.share();
答案 1 :(得分:0)
如果所需的行为是阻止从套接字进行任何更新,直到搜索输入被去抖动,那么您应该使一个流依赖于另一个,而不是合并。这可能是适用于您的用例的方法:
this.filterChange.switchMap( data => {
return Observable.of( data )
.debounceTime( 400 )
.concat( this.socketUpdates );
})
.startWith(this.filterComponent.initialValue);
.switchMap((data) => this.process(data))
.share();
我不确切知道debounceTime
运算符的用例是什么,如果您正在对文本输入或其他数据进行去抖动,但是您应该能够将其移出switchMap
如果你愿意的话。上面的这个实现可能真的很可能" chatty"订阅socketUpdates流,这也可能对您产生影响。
this.filterChange.debounceTime( 400 ).switchMap( data => {
return Observable.of( data ).concat( this.socketUpdates );
})
.startWith(this.filterComponent.initialValue);
.switchMap((data) => this.process(data))
.share();