如何记住可观察值链中的最后结果?

时间:2019-01-02 06:05:46

标签: rxjs reactive-programming system.reactive

我已经对导航概念进行了响应建模(用户在前向和后向页面中导航),但是我在使用Reactive Extensions优化它时遇到了麻烦。我确定它是某种缓冲或共享运算符,但是我不太确定它是哪一个或应该推到哪里。

这是我在TypeScript和rxjs中实现的工作的简化示例。

每次用户单击时,我们将其递增一步。 (实际上,这里存在一个网络请求,该请求可能不返回新步骤,或者不返回任何新步骤,因此为什么这不是简单的+ 1。)

describe('navigate', () => {
  it('should increment', () => {
    const initial = Observable.of(0);
    const plusOne = (ns: Observable<number>) => ns.pipe(map(n => n + 1), tap(x => console.log("Computed", x)));
    const clicks = Observable.from([plusOne, plusOne, plusOne]);
    const expected = cold("(wxyz|)", { w: 0, x: 1, y: 2, z: 3 });

    const result = clicks.pipe(
      scan(
        (s: Observable<number>, x: (ns: Observable<number>) => Observable<number>) => x(s),
        initial),
      startWith(initial),
      switchAll(),
    )

    expect(result).toBeObservable(expected);
  })
})

它产生正确的输出,并且测试通过。

但是在执行方面,您会在控制台中看到以下内容:

Computed 1
Computed 1
Computed 2
Computed 1
Computed 2
Computed 3

这是有道理的,但是如果plusOne操作很昂贵(例如,网络请求),则不会每次都从头算起plusOne

如何记忆上一个plusOne的结果,以便以后的plusOne不需要再次计算整个链? 或者,如果我以错误的方式看待这个问题,该如何解决这个问题?

尝试

自从这个问题开始以来,我确实想到了一个解决方案。

const result = clicks.pipe(
      scan(
        (s: Observable<number>, x: (ns: Observable<number>) => Observable<number>) => x(s).pipe(shareReplay(1)),
        initial),
      startWith(initial),
      switchAll(),
    )

其执行方式如下:

Computed 1
Computed 2
Computed 3

但是我认为会导致链条看起来像:

xs.map(x => x + 1).shareReplay(1).map(x => x + 1).shareReplay(1).map(x => x + 1).shareReplay(1)

,而我认为这并不是非常有效(如果每个shareReplay(1)都缓存一个值)。有更好的方法吗?

0 个答案:

没有答案