RxJs Observable:如果为空/过滤则执行函数

时间:2016-03-12 09:59:42

标签: filter angular rxjs observable rxjs5

我有一个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个不同的滤镜呢?

我是否错过任何满足我需求的方法?

提前致谢!

5 个答案:

答案 0 :(得分:4)

使用像RxJS modeling if else control structures with Observables operators

这样的分区

或者,如果前一个过滤条件为true,则使用map并管道对象,否则使用null。因此,您可以使用过滤器在链中的任何位置捕获null。

最后一个选项在过滤函数的else部分调用一些函数

答案 1 :(得分:3)

我建议有一个公共事件流,创建两个过滤流,并在订阅之前合并这两个:

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);

答案 2 :(得分:3)

如上所述,我们遇到了类似的情况,并使用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();

答案 3 :(得分:2)

我使用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 :(得分:0)

可能已经晚了,但想为仍在寻求更清洁方法来在.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,此代码将返回一个空数组,但这只是一个示例,您可以改用任何验证和表达式。