# RxJS - ajax & fromFetch operators

Date: 2021-01-29
Author: Shafiqul Islam Shuvo
Tags: RxJS, JavaScript

CRUD operations are fundamental features of any modern website or web application. Almost everyday we need to write code in the Front-End to communicate with the servers through the HTTP protocol (mostly consume data from REST Apis).

To communicate with the servers we mostly use **Fetch** api or **Axios**.

## Fetch API

**Fetch** is a built-in api of modern browsers and the problem with the **Fetch** api is that the HTTP request made through **Fetch** api isn't cancelable. There is a workaround though - we can use `AbortController` to cancel a request. But `AbortController` isn't still widely supported.

Moreover, **Fetch** api doesn't have protection against **XSRF** attack.

```javascript
fetch('url') 
  .then((response) => { 
  
    // Code for handling the response 
  }) 
  .catch((error) => { 
  
    // Code for handling the error 
  });
```

## Axios

**Axios** is a Javascript library used to make HTTP requests and it supports the ES6 **Promise** API. It also has client-side protection against **XSRF**. And we can cancel the HTTP requests using **Axios**.

```javascript
axios.get('url') 
  .then((response) => { 
  
    // Code for handling the response 
  }) 
  .catch((error) => { 
  
    // Code for handling the error 
  }) 
```

**RxJS** has a couple of operators that we can use to make HTTP requests. And the benefits of using RxJS operators are:

- **RxJS** operators return a stream of observables instead of a single promise
- **RxJS** observables are lazy. So, no HTTP request will be made until we subscribe to the observables
- The request is cancelable
- Safe against XSRF
- Tons of other powerful RxJS operators to customize the HTTP request or manipulate the data returned from the request

## RxJS/ajax

**RxJS/ajax** creates an observable for an **Ajax** request with either a request object with url, headers, etc or a string for a URL.

```javascript
import { ajax } from 'rxjs/ajax';
import { map, catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

const observable$ = ajax('url').pipe(
  map(response => console.log(response)),
  catchError(error => {
    return throwError(error);
  })
);

// Subscribing to observable
const subscription = observable$.subscribe({
  next: (data) => console.log(data),
  error: (err) => console.error(err),
  complete: () => console.log('Request is complete')
});

// Unsubscribing from the observable
subscription.unsubscribe();
```

## RxJS/fromFetch

**fromFetch** uses the **Fetch** api to make an HTTP request.

```javascript
import { of } from 'rxjs';
import { fromFetch } from 'rxjs/fetch';
import { switchMap, catchError } from 'rxjs/operators';
 
const data$ = fromFetch('url').pipe(
 switchMap(response => {
   if (response.ok) {
     // OK return data
     return response.json();
   } else {
     // Server is returning a status requiring the client to try something else.
     return of({ error: true, message: `Error ${response.status}` });
   }
 }),
 catchError(err => {
   // Network or other error, handle appropriately
   console.error(err);
   return of({ error: true, message: err.message })
 })
);
 
data$.subscribe({
 next: result => console.log(result),
 complete: () => console.log('done')
});
```

<div class="alert alert-warning">
<strong>WARNING:</strong> Parts of the <strong>Fetch</strong> API are still experimental. <strong>AbortController</strong> is required for this implementation to work and use cancellation appropriately.
</div>

<div class="alert alert-info">
<strong>fromFetch</strong> will automatically set up an internal <strong>AbortController</strong> in order to teardown the internal fetch when the subscription tears down.
</div>
