What is Reactive Programming?
Reactive Programming is fundamentally asynchronous, non-blocking, and structured around asynchronous data streams.
In Reactive programming, everything is around the propagation of changes. That means we wait until all async actions (changes) are completed and proceed with further actions.
It allows us to write Declarative code to build asynchronous processing pipelines.
An excellent example from Wikipedia:
In imperative style, if we have a statement like this one: int a = b + c; It would mean that a is assigned the result of the addition when the expression gets evaluated. If the value of variable b or c changes later, it will not affect the value of variable a.
In Reactive programming, the value of a gets automatically updated whenever the value of b or c is changed, without the program having to explicitly re-execute the statement.
It is an event-based model where we push data to consumers, and we deal with asynchronous sequences of events when they become available.
Check our Java Reactive Programming tutorials page to learn more about Reactive Programming in Java.
What is a Stream?
A stream is a sequence of ongoing events ordered in time. We can create data streams of anything (variables, collections…).
Streams can emit the following:
- some value (result)
- completed signal
- error signal
When we write the code in a Reactive way, we usually write the function that will capture the result of a stream, one function for the completed signal and one for the error signal. So all three events are handled asynchronously.
Push-Pull based model and a backpressure
We can say that Reactive Programming is a Push-Pull based model, where we first send the request, and the data is sent back as per the request.
Look at this example of an app that interacts with a database.
Here, the app requests data, and as soon as DB receives the call, the code returns immediately, so the calling thread is released to do other work. Next, another call behind the scene is sent to the DB requesting data. In this way, the app tells the DB that it is ready to consume the data. The data will be sent back to the app concurrently, as soon as it is available, in the form of a stream of events (data1, data2, data3 …).
In this way, emitters of the data can easily overwhelm the consumers. To avoid this problem, the consumer should tell the producer how much data to send. This is called Backpressure.
In Reactive programming, we can handle the backpressure by telling the data source how much data we want.
In the picture above, you see that the second call to the DB is being sent that specifies how much data we want (request(n)). We can replace n with any number. If we set 2, we will receive the stream of two events.
When these two events get processed, we have two options: asking for more data or cancelling the request.