我正在寻找一些关于如何识别哪个流进入merge
或combineLatest
功能的最佳实践建议,以便只对新流进行操作。
在TODO应用程序的上下文中,我有传入的添加和删除流,我想将它们组合在一起,以便我的列表编辑可以在无状态方式的单个流中进行。输出是一个集成了add(concat)和remove(filter)事件的列表,否则你似乎最终会得到包含所有add或remove事件的其他流,从而无限增长。
遇到的问题包括:
merge
并不表示传入了哪个流; combineLatest
并不表示哪个流已触发订阅的流,因此您不仅可以执行与该流相关的操作。withLatestFrom
会导致新的列表无法更新withLatestFrom
输入源,因此除非对此列表感兴趣的下一个流订阅该列表,否则列表将不同步(或者你有一个基于前面的新列表的每一个新列表,这导致不必要的重新步骤通过它之前发生的每个转换......)。目前发现的方法似乎不太理想包括:
type
属性明确地分配给早期流的创建对象以供识别,我认为应该避免使用RxJS方法直接识别流来自何处?[null, {addItem}]
和[removeItem, {null}]
,以便在使用merge
添加和删除事件时,我仍然可以识别正在更新的传入流,以便我可以在单个流中执行添加和删除(但后来我想添加切换事件等,但这似乎也不正确,因为我是需要创建知道所有其他潜在流的流输出(最后以[null,null,myOutput,null,null等]结束。非常欢迎任何最佳实践建议。
答案 0 :(得分:1)
您可以在合并之前操作精确流,以避免不必要的ID处理。通常使用流和函数式编程,尽量避免if-else结构,因为有工具可以帮助你。通常你可以通过查看调用的位置来避免它,并采取更早的行动。
这是一个例子。列表操作只是伪操作,以使最重要的部分可见。
let listSubject: Rx.Subject<Item[]> = new Rx.BehaviourSubject<Item[]>([]);
let addObs: Rx.Observable<Item[]> = initAddObs();
let removeObs: Rx.Observable<Item[]> = initRemoveObs();
Rx.Observable
.merge([
addObs.map(items => (list: Item[]) => list.concat(items)),
removeObs.map(items => (list: Item[]) => list.filter(items))
])
.withLatestFrom(listSubject, (operation, list) => operation(list))
.subscribe(listSubject)
对于列表,使用了BehaviourSubject,因此无论何时订阅,任何人都可以获得最新情况。 AddObs和removeObs流映射到操作,这些操作具有相同的签名并且可以合并。对当前列表执行操作后,我们必须将结果回收到listSubject。现在您可以订阅listSubject,您将获得从那里发出的最新列表。
答案 1 :(得分:0)
没有Rxjs方法可以识别流的来源。流不带有名称。如果你想要一个,你需要自己动手。因此,如果您不喜欢这两种方式,请找另一种方法为它们命名。如果您的问题是在对象上放置标识符的最佳做法,那么答案就是在该死的对象上放置一个标识符。
我个人赞成的方式是通过一个curried函数:
function label(identifier){return function (x){var obj={};obj[identifier]=x;return obj;};}
我使用如下:
source1.map(label('remove')).merge(source2.map(label('add')))
但实际上,请按照您的意愿行事,在我看来,你这样做是一个相当小的问题。