Rxjs is a library for doing reactive programming. Creation operators are useful for generating data from various data sources to be subscribed to by Observers.
In this article, we’ll look at some creation operators from Rxjs.
Ajax
We can use the ajax()
operator to fetch response objects returned from APIs.
For example, we can use it as follows:
const observable = ajax(`https://api.github.com/meta`).pipe()
map(response => {
console.log(response);
return response;
}),
catchError(error => {
console.log(error);
return of(error);
})
);
observable.subscribe(res => console.log(res));
We pipe
the data from the response with the map
operator. Also, we can catch HTTP errors with the catchError
operator.
Also, we can use ajax.getJSON()
to simplify the operation as follows:
import { ajax } from "rxjs/ajax";
import { map, catchError } from "rxjs/operators";
import { of } from "rxjs";
const observable = ajax.getJSON(`https://api.github.com/meta`).pipe()
map(response => {
console.log(response);
return response;
}),
catchError(error => {
console.log("error: ", error);
return of(error);
})
);
observable.subscribe(res => console.log(res));
Note that in both examples, we return the response
in the callback of the map
that we passed into the map
operator.
It also works for POST requests:
import { ajax } from "rxjs/ajax";
import { map, catchError } from "rxjs/operators";
import { of } from "rxjs";
const observable = ajax({
url: "https://jsonplaceholder.typicode.com/posts",
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: {
id: 1,
title: "title",
body: "body",
userId: 1
}
}).pipe(
map(response => console.log("response: ", response)),
catchError(error => {
console.log("error: ", error);
return of(error);
})
);
observable.subscribe(res => console.log(res));
As we can see, we can set headers and body of the request, so ajax
can deal with most HTTP requests.
Errors can also be caught with the catchError
operator that we pipe
in:
import { ajax } from "rxjs/ajax";
import { map, catchError } from "rxjs/operators";
import { of } from "rxjs";
const observable = ajax(`https://api.github.com/404`).pipe()
map(response => {
console.log(response);
return response;
}),
catchError(error => {
console.log(error);
return of(error);
})
);
observable.subscribe(res => console.log(res));
bindCallback
bindCallback
converts a callback API to a function that returns an Observable.
It can convert a function with parameters to an Observable by emitting the parameters.
It takes 3 arguments. The first is a function, which takes a callback function as a parameter. Whatever is passed into the callback function will be emitted by the Observable.
The second argument is an optional resultSelector
. We can pass in a function to select the emitted results here.
The last argument is an optional scheduler. We can pass in a scheduler if we want to change the way the callback function in the first argument is scheduled to be called.
import { bindCallback } from "rxjs";
const foo = fn => {
fn("a", "b", "c");
};
const observableFn = bindCallback(foo);
observableFn().subscribe(res => console.log(res));
Then we’ll see 'a'
, 'b'
and 'c'
since we passed them into our fn
callback function, which is a parameter of foo
.
Then we return a function that returns an Observable with the bindCallback
function. Then we can subscribe to the returned Observable.
defer
defer
lets us create an Observable that are only created when a subscription is made.
It takes one argument, which is an Observable factory function. For example, we can write:
import { defer, of } from "rxjs";
const clicksOrInterval = defer(() => {
return Math.random() > 0.5 ? of([1, 2, 3]) : of([4, 5, 6]);
});
clicksOrInterval.subscribe(x => console.log(x));
Then we can have an Observable that either subscribes to of([1, 2, 3])
or of([4, 5, 6])
depending on whether Math.random()
return 0.5 or less or bigger than 0.5.
empty
Creates an Observable that emits nothing to Observers except for complete notification.
It takes one optional argument, which is the scheduler that we want to use.
For example, we can use it as follows:
import { empty } from "rxjs";
const result = empty();
result.subscribe(x => console.log(x));
Then we should see nothing logged.
Another example would be to emit the value 'odd'
when odd numbers are emitted from the original Observable:
import { empty, interval, of } from "rxjs";
import { mergeMap } from "rxjs/operators";const interval$ = interval(1000);
const result = interval$.pipe(
mergeMap(x => (x % 2 === 1 ? of("odd") : empty()))
);
result.subscribe(x => console.log(x));
from
from
creates an Observable from an array, array-like object, a promise, iterable object or Observable-like object.
It takes 2 arguments, which is an array, array-like object, a promise, iterable object or Observable-like object.
The other argument is an optional argument, which is a scheduler.
For example, we can use it as follows:
import { from } from "rxjs";
const array = [1, 2, 3];
const result = from(array);result.subscribe(x => console.log(x));
We can also use it to convert a promise to an Observable as follows:
import { from } from "rxjs";
const promise = Promise.resolve(1);
const result = from(promise);
result.subscribe(x => console.log(x));
This is handy for situations where we want to do that, like converting fetch
API promises to Observables.
As we can see, the creation operators are pretty useful for turning various data sources to Observables.
We have the ajax
operator for getting HTTP request responses. The bindCallback
function turns callback arguments into Observable data. defer
let us create Observables on the fly when something subscribes to the Observable returned by the defer
operator.
Finally, we have the empty
operator to create an Observable that emits nothing, and a from
operator to create Observables from an array, array-like object, a promise, iterable object or Observable-like object.