【问题标题】:How to filter RXJS BehaviorSubject如何过滤 RXJS BehaviorSubject
【发布时间】:2021-03-22 13:27:25
【问题描述】:

我想用 BehaviorSubject 过滤数据。 当我尝试:

   public accounts: BehaviorSubject<any> = new BehaviorSubject(this.list); 
    this.accounts.pipe(filter((poiData: any) => {
      console.log(poiData)
    }));

没有工作,下面(poiData:any)是文本行错误:

没有重载匹配这个调用。重载 1 of 2, '(谓词:(值: any, index: number) => value is any, thisArg?: any): OperatorFunction',给出了以下错误。 '(poiData: any) => void' 类型的参数不能分配给 '(value: any, index: number) => value is any' 类型的参数。

我的问题是什么错误? 如何过滤 BehaviorSubject ?

【问题讨论】:

  • filter 必须返回一个值。如果在 console.log 后面加上return true; 会怎样?
  • RxJS filter != JS filter。他们俩目的不同。你到底想在这里做什么?
  • 过滤器采用一个谓词来决定哪些值是“保留”的。我在这里看到的只是对console.log 的调用,因此很难看出您使用filter 的目标是什么。
  • 请不要编辑您的帖子以将其更改为完全不同的问题。人们花时间回答了您最初的问题,并通过更改它来诋毁他们的工作。很不礼貌。如果您还有其他问题,请随时ask a new one

标签: javascript angular typescript rxjs


【解决方案1】:

您的错误发生是因为您传递给filter() 的函数返回void 而不是boolean。您可以解决该错误,但指定一个计算结果为布尔值的表达式。

但是,您的 BehaviorSubject 似乎发出了一个数组:

   public accounts: BehaviorSubject<any> = new BehaviorSubject(this.list); 

看起来您的意图是过滤数组。如果是这种情况,您不需要 filter 运算符,因为这将过滤掉排放,在您的情况下,它是完整的数组。由于您要过滤发出的数组,您应该使用 rxjs map 运算符将发出的数组映射到您使用 js Array.prototype.filter 函数过滤的数组,如下所示:

   public accounts: BehaviorSubject<any[]> = new BehaviorSubject(this.list); 
   public filteredAccounts = this.accounts.pipe(
        map(poiDataArray => poiDataArray.filter(
            acc => {
                console.log(acc);
                acc => acc.id != this.anyId;
            }
        ))
    );

这是一个简化的StackBlitz 示例:

  public numbers$ = new BehaviorSubject<number[]>([]);
  public oddNumbers$ = this.numbers$.pipe(
    // map to new array that filters out even numbers
    map(numbers => numbers.filter(n => n % 2)),
  );

【讨论】:

    【解决方案2】:

    您的问题对我来说没有意义,但这里有一些信息可能会帮助您解决问题。

    Array#filter vs RxJS#filter

    JS 对数组的过滤器非常类似于 RxJS 对 Observables 的过滤器(请记住,Subjects 也是 observables)

    例如,考虑这个谓词,如果一个数字是偶数则返回 true

    const even = n => n % 2 == 0
    

    这两段代码非常相似:

    const arr = [1,2,3,4,5,6,7,8,9];
    console.log(arr.filter(even));
    

    输出:[2,4,6,8]

    const arr = [1,2,3,4,5,6,7,8,9];
    from(arr).pipe(
      filter(even)
    ).subscribe(console.log);
    

    输出:

    2
    4
    6
    8
    

    在第一种情况下,Array#filter 返回一个数组,其中 even 为数组中的每个元素返回 true。第二个版本创建一个流,其中even 对流的每个元素(在过滤器之后)返回 true。

    非常相似。

    谓词

    谓词很容易发现。它返回一个布尔值。对或错。

    (any) => true  // This is a predicate
    (any) => false // this is a predicate
    (any) => void  // this is not a predicate.
    

    这个:

    (poiData: any) => {
      console.log(poiData);
    }
    

    (any) =&gt; void 相同。因此,您不能使用它来过滤数组或可观察对象。

    过滤 Observable 与转换 Observable

    转换 observable 的最基本方法是使用 map 运算符。 Map 更改流中的元素而不直接影响流(发射次数、它们的时间等)。

    看起来你的 observable 正在发出一个数组(或某种列表)。

    public accounts: BehaviorSubject<any> = 
      new BehaviorSubject(/* ---> */ this.list /* <--- */); 
    

    在这种情况下,您可能不是要更改流,而是要更改其元素。也许看起来像这样:

    accounts.pipe(
      map(list => list.filter(element => /* code that returns true or false */))
    ).subscribe(console.log);
    

    但是,当然,您也可以过滤流本身,以确定您的 BehaviourSubject 持有的列表是否由相应的 observable 发出。

    accounts.pipe(
      filter(list => /* code that returns true or false */)
    ).subscribe(console.log);
    

    【讨论】:

    • 是的,这是工作。清单是关键.. 但还有一个问题。我需要取消订阅此订阅吗?
    • 第二个问题......任何时候订阅的结果都是好的任何时候是空数组[]?为什么什么?如何
    猜你喜欢
    • 1970-01-01
    • 2017-05-04
    • 2018-08-31
    • 2021-04-19
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 2018-08-31
    相关资源
    最近更新 更多