RxJs Observable:如果 empty/filtered 则执行函数
RxJs Observable: Execute function if empty/filtered
我有一个 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 个不同的过滤器呢?
我是不是漏掉了满足我需求的方法?
提前致谢!
我建议有一个公共事件流,创建两个过滤流,并在订阅前合并这两个流:
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);
要么像这里那样使用分区
或者,如果前一个过滤条件为 true 或为 null,则使用 map 和 pipe 对象而不是 filter。这样您就可以使用过滤器在链中的任意位置捕获 null。
最后一个选项在过滤函数的 else 部分调用一些函数
我使用 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
属性 and/or userInput.statusChanges
Observable 来跟踪输入值。
我们有过类似的情况,并如上所述使用 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();
可能已经晚了,但想要 post 成员仍在寻求更简洁的方法来验证 .map 中的 IF EMPTY:
of(fooBar).pipe(
map(
(val) =>
({
...val,
Foo: (val.Bar
? val.Foo.map((e) => ({
title: e.Title,
link: e.Link,
}))
: []) as fooModal[],
}));
此代码 returns 如果缺少 val.bar 则为空数组,但这只是一个示例,您可以改用任何验证和表达式。
我有一个 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 个不同的过滤器呢?
我是不是漏掉了满足我需求的方法?
提前致谢!
我建议有一个公共事件流,创建两个过滤流,并在订阅前合并这两个流:
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);
要么像这里那样使用分区
或者,如果前一个过滤条件为 true 或为 null,则使用 map 和 pipe 对象而不是 filter。这样您就可以使用过滤器在链中的任意位置捕获 null。
最后一个选项在过滤函数的 else 部分调用一些函数
我使用 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
属性 and/or userInput.statusChanges
Observable 来跟踪输入值。
我们有过类似的情况,并如上所述使用 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();
可能已经晚了,但想要 post 成员仍在寻求更简洁的方法来验证 .map 中的 IF EMPTY:
of(fooBar).pipe(
map(
(val) =>
({
...val,
Foo: (val.Bar
? val.Foo.map((e) => ({
title: e.Title,
link: e.Link,
}))
: []) as fooModal[],
}));
此代码 returns 如果缺少 val.bar 则为空数组,但这只是一个示例,您可以改用任何验证和表达式。