========
Subjects
========
You can think of a "Subject" as being a tube that is open at both sides.
Whatever you put in on one side, pops out at the other end. Subjects combines
both the ``IAsyncObservable<'a>`` and ``IAsyncObserver<'a>`` interfaces.
Whatever you put in (e.g ``OnNextAsync``) at one side (``IAsyncObserver<'a>``)
will come out of the other end (``IAsyncObservable<'a>``).
The subject in FSharp.AsyncRx is very similar to the classic `Subject` in
`ReactiveX `_. The difference is that a is not a single
object, but a tuple of two *entangled* objects where one implements
``IAsyncObserver<'a>``, and the other implements ``IAsyncObservable<'a>``. This
solves the problem of having a single object trying to be two things at once
(what is the dual of an ``ISubject<'a>`` anyways?).
There are currently 3 types of subjects in AsyncRx, **subject**,
**mbSubject** and **singleSubject**.
.. val:: subject
:type: unit -> IAsyncObserver<'a> * IAsyncObservable<'a>
The subject will forward any notification pushed to the
``IAsyncObserver<'a>`` side to all observers that have subscribed to
the ``IAsyncObservable<'a>`` side. The subject is hot in the sense
that if there are no observers, then the notification will be lost.
.. code:: fsharp
let dispatch, obs = AsyncRx.subject ()
let main = async {
let! sub = obs.SubscribeAsync obv
do! dispatch.OnNextAsync 42
...
}
Async.StartImmediate main ()
.. val:: mbSubject
:type: unit -> MailboxProcessor> * IAsyncObservable<'a>
The Mailbox Subject is the same as a ``subject`` except that the observer
is exposed as a ``MailboxProcessor>``. The mailbox subject
is hot in the sense that if there are no observers, then any pushed
notification will be lost.
.. code:: fsharp
let dispatch, obs = AsyncRx.mbSubject ()
let main = async {
let! sub = obs.SubscribeAsync obv
do dispatch.Post (OnNext 42)
...
}
Async.StartImmediate main ()
.. val:: singleSubject
:type: unit -> IAsyncObserver<'a> * IAsyncObservable<'a>
The singleSubject will forward any notification pushed to the
``IAsyncObserver<'a>`` side to a single observer that have subscribed to
the ``IAsyncObservable<'a>`` side. The singleSubject is "cold" in the sense
that if there's no-one observing, then the writer will be awaited until
there is a subscriber that can observe the value being pushed. You can use
a singleSubject in scenarios that requires so called backpressure.
.. code:: fsharp
let dispatch, obs = AsyncRx.singleSubject ()
let main = async {
let! sub = obs.SubscribeAsync obv
do! dispatch.OnNextAsync 42
...
}
Async.StartImmediate main ()