【问题标题】:RxJS observable which emits both previous and current value starting from first emissionRxJS observable 从第一次发射开始发射先前值和当前值
【发布时间】:2018-04-27 09:42:26
【问题描述】:

我有一个BehaviorSubject,它会定期发出 JavaScript 对象。我想构建另一个 observable,它将发出底层 observable 的先前值和当前值,以便比较两个对象并确定增量。

pairwise()bufferCount(2, 1) 运算符看起来很合适,但它们仅在缓冲区填满后才开始发射,但我要求此 observable 从底层 observable 的第一个事件开始发射。

subject.someBufferingOperator()
    .subscribe([previousValue, currentValue] => {
        /** Do something */
    })
;

在第一次发射时,previousValue 可能只是 null

是否有一些内置运算符可以用来实现所需的结果?

【问题讨论】:

    标签: rxjs observable


    【解决方案1】:

    实际上,就像将 pairwise()startWith() 运算符配对一样简单:

    subject
        .startWith(null) // emitting first empty value to fill-in the buffer
        .pairwise()
        .subscribe([previousValue, currentValue] => {
            if (null === previousValue) {
                console.log('Probably first emission...');
            }
        })
    ;
    

    【讨论】:

    • 如果前一个或当前值是null 但它不是第一次发射怎么办。如何检测?
    • @FARID 如果你真的需要这样的确定性,我相信你可以startWith(new Symbol('First emission')),或者只是为此使用一个标志。
    • 不幸的是,这不是一个非常适合 TypeScript 的解决方案。现在previousValuecurrentValue 都有... | null 类型。有没有办法不将null 添加到currentValue 的类型中?
    • @thorn̈ 你总是可以手动将 observable 转换为所需的类型,例如as Observable<[null | Type, Type]>.
    【解决方案2】:

    这是 rxjs 6+ 的 sn-p

    subject
        .pipe(
           startWith(undefined),
           pairwise()
        )
        .subscribe(([previousValue, currentValue]) => {
            /** Do something */
        });
    

    startWith() 中的值应该是undefined,因为没有值。通常null 被定义为“我们有一个值,这个值是空的”。

    【讨论】:

      【解决方案3】:

      这是一个简单的运算符:

      function withPreviousItem<T>(): OperatorFunction<
        T,
        {
          previous?: T;
          current: T;
        }
      > {
        return pipe(
            startWith(undefined),
            pairwise(),
            map(([previous, current]) => ({
              previous,
              current: current!
            }))
          );
      }
      

      这样做的好处是结果具有有意义的属性名称和正确的类型:

      • previousT | undefined
      • currentT(不是 T | null

      Stackblitz example

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多