Combining RxJS observables - Part 1

February 20, 2024 · Updated on March 09, 2024

In my latest project, which leaned heavily on RxJS, I encountered a particularly tricky scenario that involved merging observables. Picture this: two observables are at play, but one is emitting values at a much higher frequency than the other. Faced with this challenge, I had two options I could think of: combineLatest and withLatestFrom.

The choice between them significantly impacted the behavior of the combined observables. For those who want to dive deeper, I highly recommend exploring the links and diagrams provided by the RxJS team. But to give you a clearer picture, let me walk you through the contexts I was dealing with:

Rx.combineLatest

Scenario: Imagine a live dashboard that constantly updates with the latest stock price alongside the user's current account balance, aiming to calculate and display potential investment returns. Here, the stock price is refreshed every second, while the account balance changes sporadically with user transactions.

  • Stock Price Observable (stockPriceObservable): Emits the latest stock price.
  • Account Balance Observable (accountBalanceObservable): Emits the latest account balance.

For this setup, the following snippet works wonders:

Rx.combineLatest([stockPriceObservable, accountBalanceObservable])
  .subscribe(([latestStockPrice, currentAccountBalance]) => {
    const potentialReturn = calculatePotentialReturn(latestStockPrice, currentAccountBalance);
    updateDashboard(potentialReturn);
  });

Our goal was to ensure the dashboard reflected the most up-to-date information, whether the stock price or account balance changed. combineLatest was perfect for this, guaranteeing that the dashboard always displayed the latest figures from both observables.

Rx.withLatestFrom

Scenario: Consider an application designed for placing orders on items. This app checks for the latest promo code discount when the "Place Order" button is clicked, but it's crucial that it only fetches the most recent discount code at the moment of order placement.

  • Place Order Button Click Observable (placeOrderClickObservable): Fires off an event whenever the "Place Order" button is clicked.
  • Promo Code Discount Observable (promoCodeDiscountObservable): Emits the most current discount percentage when a new promo code is activated.

Here's how you can implement it:

placeOrderClickObservable.pipe(
  Rx.withLatestFrom(promoCodeDiscountObservable),
  .subscribe(([clickEvent, latestPromoDiscount]) => {
    applyDiscount(latestPromoDiscount);
    placeOrder();
  });

In this scenario, the main focus is on the user's action of clicking the "Place Order" button. At that precise moment, we need the latest promo code discount to apply to the order. It's crucial that the order placement logic is triggered by the button click, not by the discount observable, which only provides the necessary discount information when needed.