RxJs Observable:如果为空/过滤则执行函数
Posted
技术标签:
【中文标题】RxJs Observable:如果为空/过滤则执行函数【英文标题】:RxJs Observable: Execute function if empty/filtered 【发布时间】:2016-06-27 15:22:42 【问题描述】:我有一个 Observable 可以监听来自文本框的一些用户输入。如果观察到的字符串长度 >=3 (filter
),它将执行一些 HTTP 调用 (switchMap
)。
现在我想以某种方式检测用户输入是否已被过滤。原因:
如果 HTTP 调用已经完成,它应该会显示结果。
如果用户输入被过滤(== 无效),它应该清除结果。
这是我想要的代码(请参阅:ifFiltered
):
this.userInput.valueChanges
.filter(val => val && val.length >= 3)
.ifFiltered(() => this.results = [])
.switchMap(val => getDataViaHTTP())
.subscribe(val => this.results = val);
我知道,对于这个简单的示例,我可以将该逻辑放在 filter
函数中。但是如果我有 10 个不同的过滤器呢?
我是否错过了任何满足我需求的方法?
提前致谢!
【问题讨论】:
【参考方案1】:我建议有一个共同的事件流,创建两个过滤流,并在订阅前合并两者:
var o = this.userInput.valueChanges;
var empty= o.filter(t=> t.length < 3)
.map(t=>[])
var nonempty = o.filter(t=> t.length >= 3)
.switchMap(t=> getDataViaHTTP());
empty.merge(nonempty).subscribe(val => this.results = val);
【讨论】:
看起来很不错,但是如果有 5 个过滤器,你会怎么做呢?我不想用正面和负面的方式来写每个过滤器。 您可以保存合并的过滤器,并以多种方式将其与其他流结合起来。正/负过滤器只是在开始。【参考方案2】:要么使用这里的分区RxJS modeling if else control structures with Observables operators
或者,如果前一个过滤条件为真,则使用映射和管道对象代替过滤器,否则为空。这样您就可以使用过滤器在链中的任意位置捕获 null。
最后一个选项调用过滤函数else部分中的某个函数
【讨论】:
看起来有点老套,但使用o.map(val => (val && val.length >= 3)?val:null).subscribe(val => this.results = val==null ? [] : val)
还是很不错的@
什么是“过滤函数的else部分”?【参考方案3】:
我使用Validators
为我的用例找到了另一个不错的解决方案:
(我知道这不是问题所述使用 Observables 的解决方案。相反,它使用 Angular2 功能很好地解决了这个问题。)
this.userInput.validator = Validators.compose([
Validators.required,
Validators.minLength(3)
]);
this.userInput.valueChanges
.filter(val => this.userInput.valid)
.switchMap(val => getDataViaHTTP())
.subscribe(val => this.results = val);
现在我可以使用userInput.valid
属性和/或userInput.statusChanges
Observable 来跟踪输入值。
【讨论】:
【参考方案4】:我们有一个类似的案例,并尝试使用上面提到的partition
,但发现在这里使用throw
更方便。所以对于你的代码
this.userInput.valueChanges
.do(val =>
if (!val || val.length < 3)
throw new ValueTooShortError();
)
.switchMap(val => getDataViaHTTP())
.do(val => this.results = val)
.catch(() => this.results = [])
.subscribe();
【讨论】:
【参考方案5】:可能已经晚了,但想为仍在寻求更清洁方法来验证 .map 中的 IF EMPTY 的成员发帖:
of(fooBar).pipe(
map(
(val) =>
(
...val,
Foo: (val.Bar
? val.Foo.map((e) => (
title: e.Title,
link: e.Link,
))
: []) as fooModal[],
));
如果缺少 val.bar,此代码将返回一个空数组,但这只是一个示例,您可以改用任何验证和表达式。
【讨论】:
以上是关于RxJs Observable:如果为空/过滤则执行函数的主要内容,如果未能解决你的问题,请参考以下文章
Rxjs 过滤器运算符不适用于 Angular2 Observable