avatarRakia Ben Sassi

Summary

The article distinguishes between Promises, Observables, and Streams in modern programming, emphasizing their roles in handling asynchronous operations in JavaScript and Java.

Abstract

The web development article delves into the differences between Promises, Observables, and Streams, which are fundamental concepts in managing asynchronous operations. Promises handle single events, resolving or rejecting once, while Observables manage multiple events over time and can be canceled. Streams are similar to Observables but differ in their pull-based nature and synchronous handling in Java. The article also contrasts Java 8 Streams API with RxJava, highlighting their distinct use cases and threading behaviors. It underscores the importance of understanding these concepts for efficient error handling, data manipulation, and concurrent task execution in modern web applications.

Opinions

  • The author believes that understanding the nuances between Promises, Observables, and Streams is crucial for developers to effectively manage asynchronous operations in web development.
  • Observables are presented as a more versatile tool compared to Promises, offering features like multiple values over time, pipelines, and powerful functions such as combining different Observables.
  • The reactive approach, exemplified by Observables, is advocated for its efficiency in handling sequences of asynchronous events, as opposed to the synchronous and potentially time-consuming approach of waiting for each event to complete before proceeding to the next.
  • The author suggests that while Java 8 Streams and RxJava's Observables share similar operators, they are not interchangeable due to RxJava's focus on asynchronous programming and concurrent tasks, which may lead to slower performance for certain operations.
  • RxJava is noted to be single-threaded by default, which may be surprising to those familiar with the multi-threaded nature of Java 8 Streams, and the use of Schedulers in RxJava is highlighted as a way to manage threading.
  • The article implies that mastering these concepts can lead to better performance and maintainability in web applications, as well as a clearer understanding of how to work with asynchronous data streams effectively.

Web Development

What Are The Differences Between Promises, Observables, and Streams?

3 Flavors in modern programming

Photo by Nathan Dumlao on Unsplash

Inspired by a discussion with a colleague of mine who wanted to know if Observables and promises are the same things, I decided to write this article to explain the differences between them.

You can check my video course on Udemy: How to Identify, Diagnose, and Fix Memory Leaks in Web Apps.

Promises vs. Observable

Both Promises and Observables help us to work with the asynchronous functionalities in JavaScript. Promises are values that will resolve in asynchronous ways like HTTP calls. They handle a single event when an asynchronous operation completes or fails.

Observables are like Promises, except they work with multiple values, they clean up after themselves, they can be canceled. If the result of an HTTP request or some asynchronous operations isn’t needed anymore, the Subscription of an Observable allows canceling the subscription, while a Promise will eventually call the success or failed callback even when you don’t need the notification or the result it provides anymore.

An Observable is like a Stream (in many languages) and allows to pass 0, 1, or more events where the callback is called for each event. They deal with a sequence of asynchronous events.

Observables provide the features of Promise and more:

  • They can have multiple values over time: if we keep the subscription to the newsletter open, we will get the next produced values. The sender decides when we get it, but we have to wait until it comes.
  • They have multiple pipelines
  • They support aggregate operations like map, filter, forEach, reduce, …
  • We can do some powerful functions like combining different Observables to a new one with zip, merge orconcat.
Using Observable in an Angular app to handle user’s authentication

Since Observables are used in reactive programming which deals with a “sequence of asynchronous events”, let’s see with this real-life example from Uladzimir Sinkevich what does this mean:

Say, it’s Friday and John wants to spend this evening with his friend Bob, scarfing pizza and watching one of the Star Wars episodes. Let’s outline the options he has.

  1. John finishes his work. Then goes and orders the pizza, waits till it’s done. Then picks up his friend. And finally (with Bob and pizza) makes it home and gets down to the movie. It will be the sync approach and it will be way too long so that probably John will have wanted to call the thing off by that time.
  2. John orders his pizza online, phones Bob, invites him to come. He heads home, has his pizza delivered, and starts watching the movie (and eating the pizza) without waiting for Bob to show up. That is what can happen with the async approach.
  3. John orders pizza, phones Bob, invites him to come, heads home, and gets his pizza delivered. But this time, he waits until Bob comes, and only after that, he turns the movie on. This is what the reactive approach is about. You wait till all async actions (changes) are completed and then proceed with further actions.

“Reactive programming is programming with asynchronous data streams.” Andre Staltz

Observable vs. Streams

At this stage and after seeing what we can do with an Observable, my colleague asked the next good question: “Can we handle an Observable (in frontend) the same way we handle streams in Java since they have similar operators?”

Observable and Streams look pretty similar. They have look alike operators (filter, map, …) but Observable differs from Streams significantly:

  • A Stream is simply a Collection that arrives over time.
  • Observables are like collections… except they arrive over time asynchronously.
  • Stream can only be used once, Observable can be subscribed to many times.
  • Stream is pull-based: the data-consumer decides when it gets data from the data-producer. The producer is unaware of when data will be delivered to the consumer. This only works with synchronous things. To pull a value from a collection, it has to be available now! If we think about synchronous as “pull”… we can think about asynchronous as “push”…
  • Observable is push-based: the data producer (the creator of the newsletter) decides when the consumer (the subscriber to the newsletter gets data). Promises are the most common way to push in Javascript. A promise (the producer) delivers a resolved value to registered callbacks (the consumers), but unlike functions, it is the promise which is in charge of determining precisely when that value is pushed to the callbacks.

Every Javascript function uses the pull; the function is a producer of data, and the code that calls the function is consuming it by pulling out a single return value from its call.

An Observable is a producer of multiple values, pushing them to subscribers. We subscribe to an Observable and we will get notified when the next item arrives onNext, or when the stream is completed onCompleted, or when an error occurred onError. Because with Observable we receive onNext, onCompleted, onError events. Other stuff we could do is caching, throttling, ...

Pull with Iterator vs Push with Observable
Iterator vs Observable in Java

Java 8 Streams API vs RxJava

Let’s take the example of Streams from Java 8 Streams API (java.util.stream) and Observables from RxJava (the ReactiveX API for Java, for asynchronous programming with observable streams). Those 2 APIs are not built for the same usage.

  • We can perform asynchronous tasks using RxJava.
  • With Java 8 stream, we will traverse items of your collection.
  • We can do pretty much the same thing in RxJava (traverse items of a collection) but, as RxJava is focussed on the concurrent tasks, …, it uses synchronization, latch, … So, the same task using RxJava may be slower than with Java 8 stream.
  • RxJava can be compared to CompletableFuture, but that can be able to compute more than just one value.
  • By default RxJava is single-threaded. Unless we start using Schedulers, everything will happen on the same thread.
Backend implementation: REST method returning an Observable

One last thing: Streams vs. Collections

As you’ve noticed, there is a fourth player in our story: it’s the Collection. Java 8 Streams API provides a mechanism to work with Java collections. It’s about converting collections to a stream, processing the elements in parallel, and then gathering the resulting elements into a collection.

  • A collection is an in-memory data structure that holds elements within it. Each element in the collection is computed before it actually becomes a part of that collection. So, it’s a set of eagerly computed values.
  • Streams are fixed data structures which computes the elements on-demand basis. The Java 8 Streams can be seen as lazily constructed Collections, where the values are computed when the user demands it.
  • Like functional programming languages, streams support aggregate operations that can be executed in series or in parallel: filter, map, reduce, find, match, sort, limit, collect, …
  • Streams also support Pipelining and Internal Iterations: most of java 8 stream operations return Streams only. This helps us create a chain of various stream operations → this is called pipelining. The pipelined operations look similar to SQL Query.

That’s it for today

Let me know your thoughts on this. I hope that was helpful to enhance your understanding of promise, observable, and stream and that next time you come across those terms they will not confuse you.

Want more?

I write about engineering, technology, and leadership for a community of smart, curious people 🧠💡. Join my free email newsletter for exclusive access or sign up for Medium here.

You can check my video course on Udemy: How to Identify, Diagnose, and Fix Memory Leaks in Web Apps.

JavaScript
Web Development
Programming
Software Engineering
Software Development
Recommended from ReadMedium