In this tutorial we are going to implement reactive programming with the help of streams, and with Bacon.js in particular.
Below is a mapping from reactive programming to Bacon.js – the mapping is in a descending level of abstraction.
Reactive programming
↓
Stream programming
↓
The Bacon.js library (alternatives: RxJS or Kefir)
Let’s start by comparing promises and streams. Here we assume that you have used the promise abstraction.
There are several abstractions that attempt to make it easier to deal with asynchronous code. The promise and stream abstractions are one of them. An important difference between these two abstractions is that a promise deals with a singular result, whereas a stream deals with multiple results.
In other words, a promise says that it will give you back one asynchronous result. A stream says that it will provide you with potentially infinite number of values.
Bacon.js provides a set of functions that let you create streams of values (or event streams, as they are often called).
Let’s use the Chrome console as our JavaScript environment. Open the Developer
Tools on this page (on Mac, press ⌥+⌘+J
).
Then create a stream:
numberStream = Bacon.sequentially(500, [1,2,3])
You’ve just defined a stream of numbers 1, 2 and 3, which will appear with the interval of 500 milliseconds. Contrary to many promise implementations, Bacon.js is lazy. This means that the stream is not evaluated unless it has a side effect. Our stream does not yet have one. Let’s define it:
numberStream.onValue(number => {
console.log(number)
})
Above, we used the onValue
function, which told the numberStream
that it’s
services are needed by the side-effecting console.log
function.
Create a stream that emits the value “hello” after 1 second. Then define a side effect that prints that value into the console.
Tip: here you can find the function that creates a delayed stream.
We have now taken a look at the stream abstraction. We’ve also gotten our hands warm with Bacon.js.
Next, let’s dive into the world of combinators.