【问题标题】:Filtering a BehaviorSubject过滤 BehaviorSubject
【发布时间】:2019-04-09 09:31:58
【问题描述】:

我有一个BehaviorSubject,我希望能够使用filter,但要保持其类似于行为主题的质量,即新订阅者在订阅时总是会获得一个值,即使最后发出的值已被过滤出去。有没有使用 rxjs 的内置函数的简洁方法?例如:

const isEven = (n) => n % 2 === 0;
const source = new BehaviorSubject(1);
const stream = source.pipe(filter(isEven));
stream.subscribe((n) => console.log(n)); // <- I want this to print `1`
source.next(2); // prints `2`; that's good
source.next(3); // does not print anything; that's good

我已经编写了自己的实现,但如果容易的话,我更喜欢使用现有运算符的更简单的解决方案。

【问题讨论】:

    标签: rxjs


    【解决方案1】:

    只需使用第二个 BehaviorSubject

    const { BehaviorSubject } = rxjs;
    const { filter} = rxjs.operators;
    
    const isEven = (n) => n % 2 === 0;
    const source = new BehaviorSubject(1);
    const stream = new BehaviorSubject(source.getValue());
    
    source.pipe(filter(isEven)).subscribe(stream);
    
    stream.subscribe(val => { console.log(val); });
    source.next(2);
    source.next(3);
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 好的,这很简单。凉爽的。我认为中间部分也可以简化为source.pipe(filter(isEven)).subscribe(stream)
    • 我意识到,我下班后,已经是星期五下午很晚了,啤酒点钟在响。
    • 如果过滤器为假,stream 会被分配一个默认值,而不是根本不获取新值,您将如何做到这一点?
    • 看来我应该使用map 而不是filter(请原谅我对 RxJS 的陌生)
    【解决方案2】:

    Adrian 的回答得到了赞誉,鉴于 rxjs 本身提供的内置运算符,他的回答似乎是最佳方式。它并不能完全满足我的需求,所以我在我的小库s-rxjs-utils 中发布了我的自定义运算符。它叫filterBehavior()。来自文档:

    filter() 一样工作,但总是让每个新订阅者的第一次发射通过。这使其适用于希望 observable 表现得像 BehaviorSubject 的订阅者,其中第一次发射在调用 subscribe() 期间同步处理(例如 Angular 模板中的 async 管道)。

    【讨论】:

      【解决方案3】:

      您的 stream 已通过管道传输以使用 isEven 过滤器,因此您的初始值 1 未显示在您的控制台中,其行为符合预期。

      如果你想看到你的初始值1,直接订阅BehaviourSubject

      const isEven = (n) => n % 2 === 0;
      const source = new BehaviorSubject(1);
      const stream = source.pipe(filter(isEven));
      
      // should print 1, and should print 2 and 3 when your source is nexted.
      source.subscribe((n) => console.log(n)); 
      
      stream.subscribe((n) => console.log(n)); // <- should NOT Print 1, because it has been filtered
      source.next(2); // prints `2`; that's good
      source.next(3); // does not print anything; that's good
      

      【讨论】:

      • 对不起 - 我不能很好地表达我的问题。我知道这就是为什么它的行为不同,我想知道如何让它表现得那样。我想知道如何构造 stream 以便它在我列出的时间打印东西。我会回去尝试改写问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-22
      • 1970-01-01
      • 2021-07-20
      • 2018-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多