RxJS essentials. Part 4: Using Subject

In this article I’ll introduce an RxJS Subject. The previous articles in this series include:

1. Basic Terms
2. Operators map, filter, and reduce
3. Using Observable.create()

A RxJS Subject is an object that contains the observable and observer(s). This means that you can push the data to its observer(s) using next() as well as subscribe to it. A Subject can have multiple observers, which makes it useful when you need to implement for multi-casting – emit a value to multiple subscribers.

Say, you have an instance of a Subject and two subscribers. If you push a value to the subject, each subscriber will receive it.

const mySubject = new Subject();

const subscription1 = mySubject.subscribe(...);

const subscription2 = mySubject.subscribe(...);

...

mySubject.next(123); // each subscriber gets 123

The following example has one Subject with two subscribers. The first value is emitted to both subscribers, and then one of them unsubscribes. The second value is emitted to one active subscriber.

const mySubject = new Subject();

const subscriber1 = mySubject
    .subscribe( x => console.log(`Subscriber 1 got ${x}`) ); // <1>

const subscriber2 = mySubject
    .subscribe( x => console.log(`Subscriber 2 got ${x}`) ); // <2>

mySubject.next(123);  // <3>

subscriber2.unsubscribe();  // <4>

mySubject.next(567);  // <5>

1. Create the first subscriber
2. Create the second subscriber
3. Push the value of 123 to subscribers (we have two of them)
4. Unsubscribe the second subscriber
5. Push the value of 567 to subscribers (we have just one now)

Running this script produces the following output on the console:

Subscriber 1 got 123
Subscriber 2 got 123
Subscriber 1 got 567

To see it in CodePen, visit the following link: https://codepen.io/yfain/pen/JyxvyK?editors=1011

Now let’s consider a more practical example. A financial firm has traders who can place orders to buy or sell stocks. Whenever the trader places an order, it has to be given to two scripts (subscribers):

1. The script that knows how to place orders with a stock exchange.
2. The script that knows how to report each order to a trade commission that keeps track of all trading activities.

The following code sample shows how to ensure that both of the above subscribers can receive the orders as soon as a trader places them. We create an instance of the Subject called orders, and whenever we invoke next() on it, both subscribers will receive the order. I’ll write this code sample in TypeScript because using types make the code easier to read/write (at least for me), but if you want to see its JavaScript version, copy/paste the code to the TypeScript playground at http://www.typescriptlang.org/play and you’ll see the ES5 version on the right.

import {Subject} from 'rxjs/Subject';

enum Action{      // <1>
    Buy = 'BUY',
    Sell = 'SELL'
}

class Order{   // <2>
    constructor(public orderId: number, public traderId: number, public stock: string, public shares: number, public action:Action){}
}

let orders = new Subject<Order>();  // <3>

class Trader {   // <4>

    constructor(private traderId:number, private traderName:string){}

    placeOrder(order: Order){
        orders.next(order);   // <5>
    }
}

let stockExchange = orders.subscribe(   // <6>
    ord => console.log(`Sending to stock exchange the order to ${ord.action} ${ord.shares} shares of ${ord.stock}`)); 
let tradeCommission = orders.subscribe(  // <7>
    ord => console.log(`Reporting to trade commission the order to ${ord.action} ${ord.shares} shares of ${ord.stock}`));

let trader = new Trader(1, 'Joe'); 
let order1 = new Order(1, 1,'IBM',100,Action.Buy);
let order2 = new Order(2, 1,'AAPL',100,Action.Sell);

trader.placeOrder( order1);   // <8>
trader.placeOrder( order2);   // <9>

1. Use enums to declare which actions are allowed for orders
2. A class representing an order
3. A subject instance that works only with the Order objects
4. A class representing a trader
5. When an order is placed, we push it to subscribers
6. A stock exchange subscriber
7. A trade commission subscriber
8. Placing the first order
9. Placing the second order

Running the above script produces the following output:

Sending to stock exchange the order to BUY 100 shares of IBM
Reporting to trade commission the order to BUY 100 shares of IBM
Sending to stock exchange the order to SELL 100 shares of AAPL
Reporting to trade commission the order to SELL 100 shares of AAPL

To see it in CodePen follow this link: https://codepen.io/yfain/pen/wqNOeg?editors=1011

In this example, we use TypeScript enums that allow defining a limited number of constants. Placing the actions to buy or sell inside an enum provides additional type checking to ensure that our script uses only the allowed actions. If we’d just use the string constants like “SELL” or “BUY”, the developer could misspell a word (e.g. “BYE”) while creating an order. By declaring enum Action we restrict possible actions to Action.Buy or Action.Sell. Trying to use Action.Bye results in a compilation error. BTW, did you know that RxJS 5 was written in TypeScript?
In the next article of this series, we’ll get familiar with the flatMap() operator.

If you have an account at O’Reilly’s safaribooksonline.com, you can watch my video course “RxJS Essentials” there.

Advertisement

7 thoughts on “RxJS essentials. Part 4: Using Subject

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s