可观察的契约

您可能会在源代码文档和本网站页面中看到提到的“可观察的契约”,它尝试对可观察对象进行形式化定义,最初基于 2010 年微软的文档Rx 设计指南,该文档描述了其 ReactiveX 的 Rx.NET 实现。

此页面总结了可观察的契约。

通知

可观察对象通过以下通知与观察者进行通信

OnNext
传递由可观察对象发出到观察者的项目
OnCompleted
指示可观察对象已成功完成,并且不会再发出任何项目
OnError
指示可观察对象已终止,并带有一个指定的错误条件,并且不会再发出任何项目
OnSubscribe(可选)
指示可观察对象已准备好接受观察者的请求通知(请参阅下面的背压

观察者通过以下通知与可观察对象进行通信

订阅
指示观察者已准备好接收来自可观察对象的通知
取消订阅
指示观察者不再希望接收来自可观察对象的通知
请求(可选)
指示观察者希望从可观察对象接收不超过特定数量的额外 OnNext 通知(请参阅下面的背压

管理通知的契约

可观察对象可以发出零个或多个 OnNext 通知,每个通知代表一个单独发出的项目,然后它可以跟随这些发射通知,发出 OnCompleted 或 OnError 通知,但不能同时发出两者。在发出 OnCompleted 或 OnError 通知后,它可能不会再发出任何通知。

可观察对象可能根本不发出任何项目。可观察对象也可能永远不会终止,既不发出 OnCompleted 也不发出 OnError 通知。也就是说,可观察对象可以不发出任何通知、仅发出 OnCompleted 或 OnError 通知、或仅发出 OnNext 通知。

可观察对象必须按顺序(而不是并行)向观察者发出通知。它们可以从不同的线程发出这些通知,但通知之间必须有一个正式的发生之前关系。

可观察对象的终止

如果可观察对象尚未发出 OnCompleted 或 OnError 通知,观察者可能会认为它仍然处于活动状态(即使它目前没有发出项目),并且可能会向它发出通知(例如取消订阅或请求通知)。当可观察对象确实发出 OnCompleted 或 OnError 通知时,可观察对象可能会释放其资源并终止,其观察者不应再尝试与它进行通信。

OnError 通知必须包含错误原因(也就是说,使用null值调用 OnError 是无效的)。

在可观察对象终止之前,它必须首先向订阅它的所有观察者发出 OnCompleted 或 OnError 通知。

订阅和取消订阅

可观察对象可以在接收来自观察者的订阅通知后立即开始向观察者发出通知。

当观察者向可观察对象发出取消订阅通知时,可观察对象将尝试停止向观察者发出通知。但是,不能保证可观察对象在观察者向它发出取消订阅通知后不会向观察者发出任何通知。

当可观察对象向其观察者发出 OnError 或 OnComplete 通知时,这将结束订阅。观察者不需要发出取消订阅通知来结束以这种方式由可观察对象结束的订阅。

多个观察者

如果第二个观察者订阅了已经向第一个观察者发出项目的可观察对象,那么可观察对象是否会从那时起向每个观察者发出相同的项目、是否会将完整的项目序列从头开始重播给第二个观察者、还是是否会向第二个观察者发出完全不同的项目序列,这取决于可观察对象。无法保证两个观察相同可观察对象的观察者会看到相同的项目序列。

背压

背压是可选的;并非所有 ReactiveX 实现都包含背压,在包含背压的实现中,并非所有可观察对象或运算符都遵守背压。如果可观察对象检测到其观察者实现了请求通知并理解OnSubscribe通知,则它可以实现背压。

如果可观察对象实现了背压,并且其观察者使用背压,则可观察对象不会在订阅后立即开始向观察者发出项目。相反,它将向观察者发出 OnSubscribe 通知。

在接收到 OnSubscribe 通知后,观察者可以随时向其订阅的可观察对象发出请求通知。此通知请求特定数量的项目。可观察对象通过向观察者发出不超过观察者请求的数量的项目来响应此请求。但是,可观察对象还可以发出 OnCompleted 或 OnError 通知,甚至可以在观察者请求任何项目之前发出此类通知。

不实现背压的可观察对象应通过发出表示不支持背压的 OnError 通知来响应观察者的请求通知。

请求是累积的。例如,如果观察者向可观察对象发出了三个请求通知,分别为 3、5 和 10 个项目,那么无论这些请求通知何时相对于可观察对象响应发出项目的时间到达,该可观察对象都可以向观察者发出最多 18 个项目。

如果可观察对象产生的项目超过观察者请求的数量,则可观察对象是否会丢弃多余的项目、将其存储以供以后发出,或者使用其他策略来处理溢出,这取决于可观察对象。

另请参阅