将 delay(0) 与 refCount() 结合使用

Ole*_*Ole 3 javascript rxjs typescript angular

这篇文章描述了 refCount 操作符并解释了为了防止 obervable A 的取消订阅,我们必须添加delay(0)到源 observable 中,这样 th import { Observable } from "rxjs/Observable";

    const source = Observable.defer(() => Observable.of(
    Math.floor(Math.random() * 100)
    )).delay(0);
Run Code Online (Sandbox Code Playgroud)

0永远不够吗?换句话说,传递零是否保证通知将被延迟到所有m.subscribe()语句都运行完毕,假设它们都在multicast像这样的语句之后立即运行:

const m = source.multicast(() => new Subject<number>()).refCount();
m.subscribe(observer("a"));
m.subscribe(observer("b"));
Run Code Online (Sandbox Code Playgroud)

在上述情况下,我们只订阅观察者ab。如果我们在多播语句运行后订阅了 100 万个观察者,delay(0)仍能保证在第一个源通知发生之前它们都将被订阅?

Jul*_*ius 6

要理解这个问题,你必须知道:

  • Javascript 是单线程的;
  • 异步事件在事件循环中运行(又名微任务和宏任务)
  • 当 Async 事件发生时,将其添加到 Event 循环中;
  • 将异步事件添加到事件循环后,Javascript 继续同步代码;
  • 在没有留下同步代码后,它从事件循环运行事件代码。

如果您不添加,则此 Observable 将是同步的delay(0)

const source = Observable.defer(() => Observable.of(
Math.floor(Math.random() * 100)
)).delay(0);
Run Code Online (Sandbox Code Playgroud)

当第一次订阅发生时(订阅是同步代码),Observable 立即发出,因为它也是同步的。但是,如果您添加delay(0)(类似于setTimeout),Javascript 将等到所有同步代码(source.subscribe()在本例中都是)执行完毕。之后它将异步运行delay(0))。

和这里:

const m = source.multicast(() => new Subject<number>()).refCount();
m.subscribe(observer("a"));
m.subscribe(observer("b"));
Run Code Online (Sandbox Code Playgroud)

你有sourceObservable 在它的发射被传递到 后变成异步的delay(0)。那时,同步代码将继续(所有其他source.subscribe()调用),完成后,同步delay(0)将发出。

因此,即使source.subscribe()在这种情况下执行数百万次调用也是安全的。

ps

multicast(() => new Subject<number>()).refCount()完全相同share()- 它使用主题工厂进行多播,并使用.refCount