DEV Community

Cover image for 10 use case of Observables
Kinanee Samson
Kinanee Samson

Posted on

10 use case of Observables

We have looked at the concept of reactive x programming, Observables, Subjects and some operators in Rxjs. We will now look at using what we have learnt so far in our code to do common things we do without Observables normally.

Making Http Request

To make an Http Request with Observables we can import the ajax operator from the library, we will also import the map operator and the catchError operator. The map operator will allow us to map the value we receive from the request to a particular value or action, while the catchError operator will help us handle errors that arises from the request.

import { ajax } from 'rxjs/ajax'
import { map, catchError } from 'rxjs/operators'

const Users$ = ajax.getJSON('https://jsonplaceholder.typicode.com/users')
// the getJSON method on the ajax operator is used to fecth json data

Users$.pipe(
    map(users => console.log(users),
    catchError(err => console.log(err))
)

Users$.subscribe()
// logs out a list of users from json placeholder
Enter fullscreen mode Exit fullscreen mode

Post Requests

This is simpler, easier to read and maintain. We can also make post and get requests and maybe return an Observable from the error, so we can deal with in in an observer?

import { ajax } from 'rxjs/ajax'
import { of } from 'rxjs'
import { map, catchError } from 'rxjs/operators'

const Users$ = ajax({
    url: 'the-api-we-are-sending-the-data-to',
    method: 'POST', // can be PUT, PATCH, DELETE
    headers: {'Content-Type': 'application/json'},
    body: { name: 'superman'}
})

Users$.pipe(
    map(data => console.log(data)),
    catchError(err => return of(err))
)

Users.subscribe(v => console.log(v))
// should log out response from server if everything went well
// if there is an error the observer will subscribe to it and log it out too
Enter fullscreen mode Exit fullscreen mode

Combining Two Observables

We can use the mergeMap operator to combine values we get from two Observables into a single value, this might be useful if we make a post request to add a new user to the database and the API returns some data about the new user we just created for us. We can use information on that returned user to make another request to the API to retrieve some other data based on a property on the user.

import { ajax } from 'rxjs/ajax'
import { of, zip } from 'rxjs'
import { mergeMap, catchError } from 'rxjs/operators'

const User$ = ajax({
    url: 'url-to-server',
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: { hero: 'superman'}
})

User$.pipe(
    mergeMap(hero => ajax.getJSON('url-to-get-another-resource'+hero.id)),
    catchError(err => of(err))
)

User$.subscribe()
Enter fullscreen mode Exit fullscreen mode

Zip

We can also use the zip operator to combine two Observables of the same length into a single array. This is particularly useful if we make a request to two different API that return equal length of items.

import { ajax } from 'rxjs/ajax'
import { zip, of } from 'rxjs'
import { catchError, map } from 'rxjs/operators'

const marvelHeroes$ = ajax.getJSON('url-to-api').pipe(
    map(heroes => hero.name),
    catchError(err => of(err))
);
const dcHeroes$ = ajax.getJSON('url-to-api').pipe(
    map(heroes => hero.name),
    catchError(err => of(err))
)

zip(marvelHeroes$, dcHeroes$).subscribe(x => console.log(x))
Enter fullscreen mode Exit fullscreen mode

ConcatAll

We can use this operator to flatten out higher order Observables, i.e Observable of Observables, the concatAll operator subscribes to incoming Observables emitted by the higher order observable and emits the value it receives from each inner Observable.

import { ajax } from 'rxjs/ajax'
import { of, from } from 'rxjs'
import { map, catchError, concatAll } from 'rxjs/operators'

const users$ = from([1, 2, 3, 4, 5])
users$.pipe(
    map(id => ajax.getJSON('url-to-api'))
    concatAll(),
    catchError(err => of(err))
)

users$.subscribe(data => console.log(data))
Enter fullscreen mode Exit fullscreen mode

Mapping more than value on an object

We can use the switchMap operator to return more than one data on the data we receive from the API, this operator is particularly useful when we want only some properties on the data we are getting from the API.

import { ajax } from 'rxjs/ajax'
import { of } from 'rxjs'
import { switchMap, catchError } from 'rxjs/operators'

const User$ = ajax.getJSON('url-to-api')
User$.pipe(
    switchMap(user => of(user.name, user.id, user.id)),
    catchError(err => of(err))
)

User$.subscribe(x => console.log(x))
Enter fullscreen mode Exit fullscreen mode

Filtering data

We can use the filter() operator to filter the response from the server to ensure that we only get secluded data back from the response. Say we have an API that returns a list of orders, we can filter the orders and return only pending or fulfilled orders.

import { ajax } from 'rxjs/ajax'
import { of } from 'rxjs'
import { filter, catchError, map } from 'rxjs/operators'

const Orders$ = ajax.getJSON('url-to-orders-api')
Orders$.pipe(
    map(orders => orders),
    filter(order => order.status === 'pending'),
    catchError(err => of(err))
)

Orders$.subscribe(data => console.log(data))
Enter fullscreen mode Exit fullscreen mode

Taking only a part

We might make a request to an API that returns a list of items but we are only interested in the most recent data, we can use the take operator to limit the amount values we want. Let's see a typical use case.

import { ajax } from 'rxjs/ajax'
import { of, from } from 'rxjs'
import { map, take, catchError, concatAll } from 'rxjs/operators'

const users$ = from([1, 2, 3, 4])
users$.pipe(
    map(id => ajax('url'+id)),
    concatAll(),
    take(2),
    catchError(err => of(err))
)

users$.subscribe(x => console.log(x))
Enter fullscreen mode Exit fullscreen mode

The concatAll() operators listens to incoming Observables emitted by that from the map function and subscribes to it providing us with the values emitted by each observable.

Time based Operation

We can also use the time based operators that Rxjs comes baked with to make our work easier. Let's say we have an API that returns a list of posts and we want to be fetching the latest posts from the database every say 10 seconds? we can use the interval operator to achieve this.

import { ajax } from 'rxjs/ajax'
import { of, interval } from 'rxjs'
import { map, take, catchError, concatAll } from 'rxjs/operators'

const posts$ = interval(10000)
posts$.pipe(
    map(x => ajax.getJSON('url-to-post-api')),
    concatAll(),
    take(10),
    catchError(err => of(err))
)

posts$.subscribe(post => console.log(post))
Enter fullscreen mode Exit fullscreen mode

takeUntil

The above function will keep running in the background forever and performance wise this is not so smart, we can use the takeUntil operator to allow the Observable emit data for only 30secs.

import { ajax } from 'rxjs/ajax'
import { of, interval, timer } from 'rxjs'
import { map, takeUntil, take, catchError, concatAll } from 'rxjs/operators'

const psot$ = interval(10000)
post$.pipe(
    takeUntill(timer(30000)),
    map(x => ajax.getJSON('url-to-post-api')),
    concatAll(),
    take(10),
    catchError(err => of(err))
)

posts$.subscribe(post => console.log(post))
Enter fullscreen mode Exit fullscreen mode

Hope you find this useful

Top comments (0)