第三篇 ReactiveX之Subject

1,848 阅读3分钟

前言

在专栏的前两篇分别介绍了ReactiveX和Observable,本篇主要介绍一下响应式编程里面另一个非常重要的概念Subject。Subject直译过来是主题或科目的意思,这种直译过来让人很难理解其在响应编程中的真正含义,所以请跟随笔者的脚步,从基础概念一步一步的学习响应式编程。

Subject

Subject是一种桥或代理,在ReactiveX的某些实现中可用,既充当Observer又充当Observable。因为它是一个Observer,它可以订阅一个或多个Observable;因为它是Observable的,它可以发出新的项目,它还可以将观察到的项目重新发布。

由于Subject订阅了Observable,它将触发该Observable开始发射项目(如果该Observble是“冷”的,也就是说,如果它在开始发射项目之前等待订阅)。这可以使生成的Subject将原始“冷”Observable变成“热”Observable。

Subject的种类

有四种Subject是为特定的用例而设计的。这些并非在所有实现中都可用,有些实现使用其他命名约定(例如,在RxScala中,将这里的“Subject”称为“PublishSubject”):

AsyncSubject

image.png AsyncSubject发出由源Observable发出的最后一个值(并且仅发出最后一个),并且仅在该源Observble完成之后发出。(如果源Observable没有发出任何值,那么AsyncSubject也会在不发出任何值的情况下完成。)

image.png 它还将向任何后续观察者发出相同的最终值。但是,如果源Observable因错误而终止,AsyncSubject将不会发出任何项,而是简单地从源Observble传递错误通知。

BehaviorSubject

image.png 当观察者订阅BehaviorSubject时,它首先发出源Observable最近发出的项目(如果尚未发出,则为种子/默认值),然后继续发出源observer稍后发出的任何其他项目。

image.png 然而,如果源Observable因错误而终止,BehaviorSubject将不会向后续的观察者发出任何项,而是简单地传递来自源Observble的错误通知。

PublishSubject

image.png PublishSubject只向观测者发出由源Observable在订阅时间之后发出的那些项。

请注意,PublishSubject可能会在创建后立即开始发送项目(除非您已采取措施防止这种情况发生),因此在创建Subject和观察者订阅它之间,一个或多个项目可能会丢失。如果您需要保证从源Observable交付所有项目,您需要使用Create形成Observable,以便手动重新引入“冷”Observable行为(检查所有观察者在开始发出项目之前是否已经订阅),或者改用ReplaySubject。

image.png 如果源Observable因错误而终止,那么PublishSubject将不会向后续的观察者发出任何项,而是简单地传递来自源Observble的错误通知。

ReplaySubject

image.png ReplaySubject将源Observable发出的所有项目发送给任何观察者,无论观察者何时订阅。 还有一些版本的ReplaySubject,一旦重放缓冲区有超过特定大小的危险,或者当项目最初发出后经过指定的时间跨度时,就会丢弃旧项目。 如果您使用ReplaySubject作为观察者,请注意不要从多个线程调用其onNext方法(或其其他on方法),因为这可能会导致重合(非顺序)调用,这违反了Observable约定,并在生成的Subject中造成应先重放哪个项目或通知的歧义。

总结

如果没有响应式编程基础的小伙伴,单独看本篇文章可能会比较难理解,所以笔者在这里强烈建议结合本专栏前两篇的文章一起看,这样理解的会比较深刻一些。