Javascript 我可以用另一个可观测对象的多个事件操纵一个可观测对象吗?
假设我有一组映射到输入字段的验证消息。假设我们从服务器获取这些验证消息 我还有一个映射到输入字段的变更事件流 每当我得到一个给定字段的更改事件时,我想Javascript 我可以用另一个可观测对象的多个事件操纵一个可观测对象吗?,javascript,rxjs,Javascript,Rxjs,假设我有一组映射到输入字段的验证消息。假设我们从服务器获取这些验证消息 我还有一个映射到输入字段的变更事件流 每当我得到一个给定字段的更改事件时,我想 查看该字段是否有相应的验证消息 删除验证消息 这里有一个例子,希望能说明为什么通常的嫌疑犯(combineLatest,withLatestFrom)不能让我越界 combinelateest的问题是:第四个更改事件将过滤第二个验证数组 withLatestFrom的问题是:第三个更改事件将撤消第二个更改事件的工作 有人有什么建议吗?我找错树了
combinelateest
的问题是:第四个更改事件将过滤第二个验证数组
withLatestFrom的问题是:第三个更改事件将撤消第二个更改事件的工作
有人有什么建议吗?我找错树了吗?我把问题简化了吗?有没有一种RxJS方法适合这种情况 每次收到验证消息时,似乎都在重新开始处理更改事件。在这种情况下,您可以尝试以下方法:
filteredValidation$ = validation$.flatMapLatest(function ( aObjs ) {
return changeEvent$.scan(function ( acc, changeEvent ) {
return isIn(changeEvent, acc) ? removeChangeEvent(changeEvent, acc) : acc;
}, aObjs);
});
isIn
和removeChangeEvent
必须根据change\u事件的特定形状来编写,但这相当简单
- 每个验证消息都将启动一个新流
- 该流将具有一个状态,该状态由
scan
函数中的累加器acc
表示,并且该状态本身是最新过滤的验证对象
我还没有测试,但希望它能工作
顺便说一句:我喜欢你的图表,它完美地说明了你想要实现的处理。每次你有一条验证消息,似乎你都在重新开始处理更改事件。在这种情况下,您可以尝试以下方法:
filteredValidation$ = validation$.flatMapLatest(function ( aObjs ) {
return changeEvent$.scan(function ( acc, changeEvent ) {
return isIn(changeEvent, acc) ? removeChangeEvent(changeEvent, acc) : acc;
}, aObjs);
});
isIn
和removeChangeEvent
必须根据change\u事件的特定形状来编写,但这相当简单
- 每个验证消息都将启动一个新流
- 该流将具有一个状态,该状态由
scan
函数中的累加器acc
表示,并且该状态本身是最新过滤的验证对象
我还没有测试,但希望它能工作
顺便说一句:我喜欢你的图表,它完美地说明了你想要实现的处理过程。这里是另一个不同技巧的答案。这个想法是类似的(使用scan
来记住以前的值,但是我们通过一个减少函数生成当前值,该函数取决于发出值的源)
jsfiddle:
这里是另一个不同技巧的答案。这个想法是类似的(使用scan
来记住以前的值,但是我们通过一个减少函数生成当前值,该函数取决于发出值的源)
jsfiddle:
我已经修改了上面的JSFIDLE,以展示我提出的解决方案
jsfiddle:
基本上,此版本使用Rx.Observable.window
根据来自验证$
流的新事件,将changeEvents$
流分块
var filteredValidation$ = validation$
.merge(
changeEvent$
.window(validation$)
.flatMapLatest(changeWindow => {
return changeWindow.scan((acc, next) => acc.add(next), new Set());
)
.withLatestFrom(validation$, (filterSet, errs) => {
return errs.filter(err => !filterSet.has(err.key));
})
)
.distinctUntilChanged()
我已经修改了上面的JSFIDLE,以展示我提出的解决方案
jsfiddle:
基本上,此版本使用Rx.Observable.window
根据来自验证$
流的新事件,将changeEvents$
流分块
var filteredValidation$ = validation$
.merge(
changeEvent$
.window(validation$)
.flatMapLatest(changeWindow => {
return changeWindow.scan((acc, next) => acc.add(next), new Set());
)
.withLatestFrom(validation$, (filterSet, errs) => {
return errs.filter(err => !filterSet.has(err.key));
})
)
.distinctUntilChanged()
很高兴你喜欢这个图表。此解决方案产生与CombineTest相同的场景,其中第四个更改事件将过滤第二个验证数组。很高兴您喜欢此图表。此解决方案产生与CombineTest相同的场景,其中第四个更改事件将过滤第二个验证数组。谢谢。这很有效。不过我有几个问题。这看起来像是对验证流进行了变异——这被认为是惯用的/良好的做法。我“感觉”不对,但我是Rx的新手,所以我知道什么?其次,我不确定在filteredValidations.merge(validations$.map(…)
行中发生了什么。您将返回一个返回值的函数。你能解释一下你为什么这么做吗?第三个也是最不显著的点-以$..作为流的后缀。。。。我喜欢,但不能决定我是否会采用这个。这是常用的惯例吗。美元就够了:不记得我在哪里见过这个大会,但我一见钟情。我不会说它是常用的。毕竟,反应式编程还不是主流,所以惯例仍然可以接受。但是我更喜欢它而不是obsName
,或者nameObs
,而只是name
。流突变:不,我没有对流进行突变。Rx中的流大部分是不可变的。但我确实将验证对象流转换为一个简化函数流。这些函数表示要对最新筛选的验证对象执行的操作。因此,他们获取最新的验证对象并返回一个新的验证对象。最新的验证对象作为scan
函数中的prev
参数提供。是的,用高阶函数进行推理有点困难,同意。先前使用flatMapLatest
的解决方案确实更易于理解。谢谢。这很有效。不过我有几个问题。这看起来像是对验证流进行了变异——这被认为是惯用的/良好的做法。我“感觉”不对,但我是Rx的新手,所以我知道什么?其次,我不确定在filteredValidations.merge(validations$.map(…)
行中发生了什么。您将返回一个返回值的函数。你能解释一下你为什么这么做吗?第三个也是最不显著的点-以$..作为流的后缀。。。。我喜欢,但不能决定我是否会采用这个。这是我们的共同愿望吗