A simple experiment to implement infinite scroll with RxJS
Blog post on Angular Implementation : Simple Infinite Scroller directive with RxJS Observables
What is Reactive Programming ?
In simple terms it is programming with asynchronous data streams. There is a great post by Andre Staltz — The introduction to Reactive Programming you’ve been missing accompanied by an egghead.io video.
What is RxJS?
Below are a couple of nice introductions to Observables and a few operators by Netanel Basal
What will we be building?
We are going to build a naive infinite scroller using observables. Whenever the user scrolls a given container to 70%, we will trigger the api call to get more data from the server. For this implementation we will use the HackerNews unofficial api to get the latest news.
Below are the operators we will be using from RxJS
map: similar to map in an array, map over the stream of incoming data.
filter: similar to filter in an array, filter the stream of incoming data.
pairwise: returns an array of current emitted data and also the previous emitted data .
startWith: returns an observable emits supplied values before emitting the values from source observable
exhaustMap: waits to emit value until the passed in inner observable has completed
Link to the output in jsbin.com : https://output.jsbin.com/punibux
#Phase1 — Setup basic html and styles
Import the RxJS library and we will use
infinite-scroller as a scroll container and append news to it.
#Phase2 — Setup helpers functions for data processing, rendering and calculations
First three functions are straight forward,
getQuotesAPI— returns the api url with the current page number as query param
processData— processes the return data from the api which is performed using fetch API and increase the currentPage.
renderNews— takes each news item and renders to the view.
The next two functions are the ones used for scroll calculations
isUserScrollingDown — determines if the user is scrolling down or not.
isScrollExpectedPercent — determines if the user has scrolled to the passed in percentage to get more data.
#Phase3 — Setup up observable stream
To capture the scroll events in the container, we need to create an observable from the scroll event. This can be achieved by using
Rx.Observable.fromEvent- docs. It is a convention to append
$ to the variable when referencing an observable stream.
#Phase4 — Stream logic to process scroll events and call the api
We are going to take the scroll event emitted by
map over to take only the values we need for our infinite scroll logic. We need only three properties from the scroll element —
We pass the mapped data to
pairwise operator which emits the current and previous value in an array which will look like below.
Now we can take the pair of positions and pass it to the
filter them to filter according to our conditions
- Is the user scrolling down
- Has the user scrolled reached seventy percent of the container
requestOnScroll$ — It gets invoked when the
userScrollDown$ has passed filter conditions. We start with an initial value of an empty array.
We going to use
Rx.Observable.fromPromise to create an observable from a promise.
fetch makes the http call and returns a promise.
exhaustMap will wait for the fetch to complete and the inner observable to emit the data from the API.
Observables are lazy — means they do not do anything until you subscribe to them. We will subscribe to the
requestOnScroll$ and pass in
processData to the subscribe method. When
exhaustMap emits the data from the api it will be passed on to
processData which will call
renderNews to render on to the view.
Below is the gif of the infinite scroll in action, watch the scroll bar on the right.
In my next post I will try to implement it in Angular 2 by creating an infinite scroll directive.
Update: Here is the link to my follow post on Simple Infinite Scroller directive with RxJS Observables