Skip to content

Commit

Permalink
docs(manual): write content in subject.md about Subject variants
Browse files Browse the repository at this point in the history
  • Loading branch information
staltz authored and kwonoj committed Mar 8, 2016
1 parent b6ee34f commit 935212a
Showing 1 changed file with 141 additions and 1 deletion.
142 changes: 141 additions & 1 deletion doc/subject.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Internally to the Subject, `subscribe` does not invoke a new execution that delivers values. It simply registers the given Observer in a list of Observers, similarly to how `addListener` usually works in other libraries and languages.

**Every Subject is an Observer.** It is an object with the methods `next(v)`, `error(e)`, and `complete()`. To feed a new value to the Subject, just call `next(theValue)`, and it will be multicast to the Observers registered to listen to the Subject.
**Every Subject is an Observer.** It is an object with the methods `next(v)`, `error(e)`, and `complete()`. To feed a new value to the Subject, just call `next(theValue)`, and it will be multicasted to the Observers registered to listen to the Subject.

In the example below, we have two Observers attached to a Subject, and we feed some values to the Subject:

Expand Down Expand Up @@ -202,6 +202,146 @@ The `refCount()` method only exists on ConnectableObservables, and it returns an

## BehaviorSubject

One of the variants of Subjects is the `BehaviorSubject`, which has a notion of "the current value". It stores the latest value emitted to its consumers, and whenever a new Observer subscribes, it will immediately receive the "current value" from the `BehaviorSubject`.

<span class="informal">BehaviorSubjects are useful for representing "values over time". For instance, an event stream of birthdays is a Subject, but the stream of a person's age would be a BehaviorSubject.</span>

Notice in the following example how the BehaviorSubject is initialized with the value `0` which the first Observer receives when it subscribes. Also, the second Observer subscribes after the value `2` was sent, but will still receive that value:

```js
var subject = new Rx.BehaviorSubject(0 /* the initial value */);

subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});

subject.next(1);
subject.next(2);

subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});

subject.next(3);
```

With output:

```none
observerA: 0
observerA: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3
```

## ReplaySubject

The `ReplaySubject` subclass of `Subject` is like `BehaviorSubject` in that it can send old values to new incoming subscribers, but it in general is able to *record* a part of the Observable execution.

<span class="informal">A `ReplaySubject` records multiple values from the Observable execution and replays them to new subscribers.</span>

You may, for instance, specify how many values to replay, e.g.:

```js
var subject = new Rx.ReplaySubject(3 /* bufferSize */);

subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});

subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);

subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});

subject.next(5);
```

With output:

```none
observerA: 1
observerA: 2
observerA: 3
observerA: 4
observerB: 2
observerB: 3
observerB: 4
observerA: 5
observerB: 5
```

You can also specify a *window time* in milliseconds, besides of the buffer size, to determine how old the recorded values can be. In the following example we use a large buffer size of `100`, but a window time parameter of just `500` milliseconds.

<!-- skip-example -->
```js
var subject = new Rx.ReplaySubject(100, 500 /* windowTime */);

subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});

var i = 1;
setInterval(() => subject.next(i++), 200);

setTimeout(() => {
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
}, 1000);
```

With the following output where the second Observer gets events `3`, `4` and `5` that happened in the last `500` milliseconds prior to its subscription:

```none
observerA: 1
observerA: 2
observerA: 3
observerA: 4
observerA: 5
observerB: 3
observerB: 4
observerB: 5
observerA: 6
observerB: 6
...
```

## AsyncSubject

The AsyncSubject is a variant where only the last value of the Observable execution is sent to its observers, and only when the execution completes.

```js
var subject = new Rx.AsyncSubject();

subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});

subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);

subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});

subject.next(5);
subject.complete();
```

With output:

```none
observerA: 5
observerB: 5
```

The AsyncSubject is similar to the [`last()`](../class/es6/Observable.js~Observable.html#instance-method-last) operator, in that it waits for the `complete` notification in order to deliver a single value.

0 comments on commit 935212a

Please sign in to comment.