10 use case of Observables
Published: 2021-03-24 08:15:27

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.

```javascript
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
```

### 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?

```javascript
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
```



## 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.

```javascript
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()
```



### 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.

```javascript
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))
```



### 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.

```javascript
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))
```



### 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.

```javascript
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))
```



### 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.

```javascript
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))
```



### 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.

```javascript
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))
```

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.

```javascript
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))
```



### 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.

```javascript
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))
```

Hope you find this useful