Skip to content
IRC-CodingIRC-Coding
Reactive ProgrammingObservableObserverRxJSData StreamsAsynchronicity

Introduction to Reactive Programming

Learn Reactive Programming basics: Observer and Observable patterns, asynchronous data streams, operators, and practical examples.

S

schutzgeist

4 min read

Introduction to Reactive Programming

Picture a typical web application—say, an online shop.

  • A user clicks a button to view product details.
  • The application must send a request to a slow server and wait for a response.
  • Only once the response arrives can it update the page.

1. The Core Problem: Why “Reactive” at All?

The classical (imperative) model: The application blocks while waiting for the server to respond. This is inefficient. It’s like ordering at a restaurant and then holding the waiter hostage until your food is ready. Meanwhile, he can’t serve anyone else.

The reactive solution: The application tells the server: “Send me the data when it’s ready. I’m not going to wait here, but I’ll leave you my phone number. Call me back when you have something.” In the meantime, it can handle other tasks.

2. The Core Principle: Asynchronous Data Streams

Reactive Programming hinges on two central ideas:

  1. Asynchronicity: Tasks run “in the background.” The main program doesn’t block and doesn’t wait for results.
  2. Data streams: Everything can be viewed as a stream (sequence) of events: mouse clicks, keyboard input, HTTP requests, database results, and so on. These streams can be created, transformed, filtered, and combined.

3. The Analogy: The Subscription Model (Magazine vs. YouTube)

To grasp reactive thinking, compare two approaches:

Imperative (Pull Model)Reactive (Push Model)
AnalogyBuying a magazineSubscribing to a YouTube channel
ActionYou actively go to the newsstand and ask for the latest issue. (Pull)You click “Subscribe.” (Push)
FutureYou have to go back to the newsstand next week for the new issue.You get a notification as soon as a new video drops.
BenefitYou get what you want immediately.You never miss anything and don’t have to keep checking. Content comes to you.

Reactive Programming follows the subscription model (push principle). You subscribe to a data source and get notified whenever new data arrives.

4. The Key Players: Observer and Observable

This abstraction is used in nearly all reactive frameworks (like RxJava, Project Reactor).

  • Observable (or Publisher):

    • Who? The data source. It produces a stream of events or data.
    • Examples: A button (emits click events), a sensor (emits measurements), a server response.
    • Job: It manages who is interested in its data—its “subscribers.”
  • Observer (or Subscriber):

    • Who? The data consumer. It’s interested in the Observable’s data.
    • Examples: The function that reacts to a click; the logic that evaluates a sensor reading.
    • Job: It subscribes to an Observable. It must handle three different types of notifications.

5. The Three Callbacks: How the Observer Responds

The Observer tells the Observable what to do for each event by implementing three methods:

  1. onNext(T value)

    • When? Called when the Observable emits a new data element.
    • What to do? Process the received element (for example, display products or log the sensor value).
    • YouTube analogy: A new video was uploaded.
  2. onError(Throwable error)

    • When? Called when an error occurs.
    • What to do? Handle it (for example, show an error message to the user or retry).
    • YouTube analogy: An error happened while uploading the video.
  3. onComplete()

    • When? Called when the Observable will send no further data. The stream has ended.
    • What to do? Clean up.
    • YouTube analogy: The YouTuber deleted their channel. No new videos will ever come.

6. A Code Example (Conceptual)

Suppose we want to log every mouse click on a webpage.

Imperative Approach (Pseudocode)

// We actively ask (PULL)
while (true) {
  if (mouseWasClicked()) { // Blocks until a click comes!
    const clickEvent = getClickEvent(); // Gets the click
    console.log('Click at: ', clickEvent.position);
  }
}
// Problem: The whole loop blocks and just waits for clicks.

Reactive Approach (Pseudocode with RxJS)

// We subscribe to the click data source (PUSH)
fromEvent(document, 'click') // Creates an Observable from click events
  .subscribe(                // Subscribe and define callbacks
    (clickEvent) => {        // onNext: What happens on each click
      console.log('Click at: ', clickEvent.clientX, clickEvent.clientY);
    },
    (error) => {             // onError: What happens on an error
      console.error('Something went wrong: ', error);
    },
    () => {                  // onComplete: What happens at the end (never called here, since clicks never stop)
      console.log('No more clicks. Goodbye!');
    }
  );
// Benefit: The main thread isn't blocked and can do other things.
// The callback is only invoked when an event actually arrives.

7. Why Is This So Powerful? Operators!

The real strength lies in manipulating these data streams with operators, similar to map, filter, reduce in functional programming.

  • filter: Let only certain events through. (For example: only clicks within a specific div)
  • map: Transform events. (For example: convert a click event to an object like {x: 10, y: 20})
  • debounceTime: “Debounce” events. (For example: process only the last click in a rapid click sequence—perfect for search fields!)
  • merge: Combine multiple streams. (For example: merge clicks and keyboard input into one stream)
fromEvent(document, 'click')
  .pipe(
    filter(event => event.target.id === 'myButton'), // Only clicks on #myButton
    debounceTime(250),                               // Wait 250ms between clicks
    map(event => { return {x: event.clientX, y: event.clientY}; }) // Transform the event
  )
  .subscribe(coord => console.log('Clicked at: ', coord));

Summary

  • Reactive Programming is a paradigm for non-blocking, asynchronous processing of data streams.
  • It follows the push model or subscription pattern: the data consumer (Observer) subscribes to a data source (Observable).
  • The Observer responds to three kinds of events: new data (onNext), errors (onError), and completion (onComplete).
  • Through operators (like filter, map), data streams can be elegantly transformed and combined.
  • Benefits: Better resource utilization (no blocking), elegant handling of asynchronous events, easier composition of complex workflows.
Back to Blog
Share:

Nächster Artikel in Programming

Weiterlesen
Algorithms and Data Structures 2026

Related Posts