The Observable Contract

“The Observable Contract,” which you may see referenced in various places in source documentation and in the pages on this site, is an attempt at a formal definition of an Observable, based originally on the 2010 document Rx Design Guidelines from Microsoft that described its Rx.NET implementation of ReactiveX.

This page summarizes The Observable Contract.

Notifications

An Observable communicates with its observers with the following notifications:

OnNext
conveys an item that is emitted by the Observable to the observer
OnCompleted
indicates that the Observable has completed successfully and that it will be emitting no further items
OnError
indicates that the Observable has terminated with a specified error condition and that it will be emitting no further items
OnSubscribe (optional)
indicates that the Observable is ready to accept Request notifications from the observer (see Backpressure below)

An observer communicates with its Observable by means of the following notifications:

Subscribe
indicates that the observer is ready to receive notifications from the Observable
Unsubscribe
indicates that the observer no longer wants to receive notifications from the Observable
Request (optional)
indicates that the observer wants no more than a particular number of additional OnNext notifications from the Observable (see Backpressure below)

The Contract Governing Notifications

An Observable may make zero or more OnNext notifications, each representing a single emitted item, and it may then follow those emission notifications by either an OnCompleted or an OnError notification, but not both. Upon issuing an OnCompleted or OnError notification, it may not thereafter issue any further notifications.

An Observable may emit no items at all. An Observable may also never terminate with either an OnCompleted or an OnError notification. That is to say that it is proper for an Observable to issue no notifications, to issue only an OnCompleted or an OnError notification, or to issue only OnNext notifications.

Observables must issue notifications to observers serially (not in parallel). They may issue these notifications from different threads, but there must be a formal happens-before relationship between the notifications.

Observable Termination

If an Observable has not issued an OnCompleted or OnError notification, an observer may consider it to be still active (even if it is not currently emitting items) and may issue it notifications (such as an Unsubscribe or Request notification). When an Observable does issue an OnCompleted or OnError notification, the Observable may release its resources and terminate, and its observers should not attempt to communicate with it any further.

An OnError notification must contain the cause of the error (that is to say, it is invalid to call OnError with a null value).

Before an Observable terminates it must first issue either an OnCompleted or OnError notification to all of the observers that are subscribed to it.

Subscribing and Unsubscribing

An Observable may begin issuing notifications to an observer immediately after the Observable receives a Subscribe notification from the observer.

When an observer issues an Unsubscribe notification to an Observable, the Observable will attempt to stop issuing notifications to the observer. It is not guaranteed, however, that the Observable will issue no notifications to the observer after an observer issues it an Unsubscribe notification.

When an Observable issues an OnError or OnComplete notification to its observers, this ends the subscription. Observers do not need to issue an Unsubscribe notification to end subscriptions that are ended by the Observable in this way.

Multiple Observers

If a second observer subscribes to an Observable that is already emitting items to a first observer, it is up to the Observable whether it will thenceforth emit the same items to each observer, or whether it will replay the complete sequence of items from the beginning to the second observer, or whether it will emit a wholly different sequence of items to the second observer. There is no general guarantee that two observers of the same Observable will see the same sequence of items.

Backpressure

Backpressure is optional; not all ReactiveX implementations include backpressure, and in those that do, not all Observables or operators honor backpressure. An Observable may implement backpressure if it detects that its observer implements Request notifications and understands OnSubscribe notifications.

If an Observable implements backpressure and its observer employs backpressure, the Observable will not begin to emit items to the observer immediately upon subscription. Instead, it will issue an OnSubscribe notification to the observer.

At any time after it receives an OnSubscribe notification, an observer may issue a Request notification to the Observable it has subscribed to. This notification requests a particular number of items. The Observable responds to such a Request by emitting no more items to the observer than the number of items the observer requests. However the Observable may, in addition, issue an OnCompleted or OnError notification, and it may even issue such a notification before the observer requests any items at all.

An Observable that does not implement backpressure should respond to a Request notification from an observer by issuing an OnError notification that indicates that backpressure is not supported.

Requests are cumulative. For example, if an observer issues three Request notifications to an Observable, for 3, 5, and 10 items respectively, that Observable may emit as many as 18 items to the observer, no matter when those Request notifications arrived relative to when the Observable emitted items in response.

If the Observable produces more items than the observer requests, it is up to the Observable whether it will discard the excess items, store them to emit at a later time, or use some other strategy to deal with the overflow.

See Also