【问题标题】:Pipe Observable to Subject without making it hot unneccessarily管道 Observable 到 Subject 而不使其不必要地变热
【发布时间】:2021-11-23 00:24:02
【问题描述】:

这个问题建立在this one 之上,其中展示了如何将Observable 输入Subject。我的问题是类似的,但我想避免使Observable 变热,除非有必要,这样.pipe() 就不会不必要地运行。例如:

const subject$ = new Subject();
const mouseMove$ = Observable.fromEvent(document, 'mousemove')
                             .pipe(map(it => superExpensiveComputation(it)));
mouseMove$.subscribe(n => subject$.next(n));

由于订阅,这将使mouseMove$ 变得很热,并且superExpensiveComputation 将在每次鼠标移动时运行,无论是否有人在subject$ 上收听它。

如何在不不必要地运行superExpensiveComputation 的情况下将mouseMove$ 的结果输入subject$

【问题讨论】:

  • 你想达到什么目的?为什么不直接订阅mouseMove$

标签: rxjs


【解决方案1】:

您可以简单地使用 tap 而不是 subscribe 将排放传递给您的主题:

const mouseMove$ = fromEvent(document, 'mousemove').pipe(
  map(it => superExpensiveComputation(it)),
  tap(subject$)
);

当然,您仍然需要订阅 mouseMove$ 才能使数据流动,但您不需要订阅专门用于将数据传递给您的主题。

但是,您可能需要添加 share,以免为多个订阅者重复昂贵的逻辑。

const mouseMove$ = fromEvent(document, 'mousemove').pipe(
  map(it => superExpensiveComputation(it)),
  share(),
  tap(subject$)
);

但是……那么在那种情况下,你真的需要一个主题吗?除非您打算从其他地方拨打.next(),否则您可能不会。

【讨论】:

  • 是的,我需要主题才能从其他地方调用 next。真正的代码很复杂,这个问题是我能做到的。本来想用tap,但是感觉很副作用很脏,不过我觉得没问题
【解决方案2】:

因为订阅,这会让 mouseMove$ 很火

错了。订阅不会改变 observable 的行为。

Observable.fromEvent(document, 'mousemove') 已经很热了。

这是它的天真冷版。 关键点,我每次都必须重新订阅才能获得最新数据。

const { of } = rxjs;

const mouseMove$ = of((() => {
let payload = {clientX: 0};
document.addEventListener("mousemove", (ev) => payload.clientX = ev.clientX)
return payload;
})())

let subscriber = mouseMove$.subscribe(pr => console.log(pr));

const loop = () => {
  if(subscriber) {
    subscriber.unsubscribe();
  }
  
  subscriber = mouseMove$.subscribe(pr => console.log(pr));

  setTimeout(loop, 1000);
};

setTimeout(loop, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>

并且每次鼠标移动都会运行 superExpensiveComputation, 是否有人在主题$上收听它

然后您可以摆脱 map(it => superExpensiveComputation(it)) 并将该 lamda 移动到订阅状态,这样它仍然会在每次鼠标移动时执行但在订阅之后。

【讨论】:

    猜你喜欢
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多