Categories
JavaScript Rxjs

More Useful Rxjs Creation Operators

Spread the love

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 more creation operators from Rxjs, like functions that create Observables from event handlers, functions that generate Observables that emit numbers, and functions that let us conditionally subscribe to Observables.

fromEvent

The fromEvent function creates an Observable that emits event objects of the type that we specified as it happens to the event target.

It takes up to 4 arguments. The first argument is the event target. which is required. It can be a DOM event target, Node.js event emitter, jQuery like event target, NodeList, or HTMLCollection to attach event handlers to.

The second argument is the event name that’s being emitted by the event target.

The 3rd argument is an optional argument with some options.

The last argument is an optional result selector function.

Every time the Observable is subscribed to, the event handler function will be registered to the event target on the given event type.

When the event fires, the event object will emitted by the Observable.

The event targets are checked by duck typing. We can safely use fromEvent on the object on the object if it exposes the following methods:

  • DOM event target if it has the addEventLister and removeEventListener methods
  • Node.js event emitter if it has the addListener and removeListener methods
  • jQuery style objects if it has the on and off methods
  • DOM NodeLists or HtmlCollection if they have a list of DOM nodes returned by methods like document.querySelectorAll or the childNodes property of a DOM node.

We can use fromEvent as follows:

import { fromEvent } from "rxjs";
const clicks = fromEvent(window, "click");  
clicks.subscribe(x => console.log(x));

The code above watches for clicks on the document object. We should see MouseEvent objects logged when we click anywhere on the browser tab.

fromEventPattern

This is similar to fromEvent , except that we pass in handler functions for adding event listeners and removing event listeners.

It takes 3 arguments. The first 2 are the add and remove handlers respectively. The remove handler is optional. The last argument is an optional result selector function for manipulating emitted values.

For example, we can use it to detect the clicks on a div with ID app as follows:

import { fromEventPattern } from "rxjs";
const app = document.querySelector("#app");

function addClickHandler(handler) {  
  app.addEventListener("click", handler);  
}

function removeClickHandler(handler) {  
  app.removeEventListener("click", handler);  
}

const clicks = fromEventPattern(addClickHandler, removeClickHandler);  
clicks.subscribe(x => console.log(x));

We should see MouseEvent objects logged when we click anywhere on a div with the ID app .

generate

The generate function creates an Observable with a stream of values by passing in the initial state, a function with the condition for the ending the emitting of values, a function for iterating through the values, result selector function for selecting the emitted results, and a scheduler object for changing the timing for emitting the values.

Only the initial state is required. For example, we can create an Observable that emits the values 0 to 9 by writing:

import { generate } from "rxjs";
const generated = generate(0, x => x < 10, x => x + 1);  
generated.subscribe(  
  value => console.log(value),  
  err => {}  
);

The first argument of the generate function call has the first value to emit or the initial state. The second has the ending condition, which is less than 10. The last argument has the function that indicates how to move on and emit the next item and move towards the ending condition in the second argument.

interval

interval creates an Observable that emits sequential numbers in a specified interval of time.

It takes 2 optional arguments. The first is the number of milliseconds or the time unit determined by the scheduler’s clock. The default is 0.

The second argument is the scheduler to use, which defaults to async .

For example:

import { interval } from "rxjs";
const numbers = interval(1000);

creates an Observable that emits a new value every second.

of

This creates an Observable out of its arguments.

It takes an infinite number of arguments.

For example, we can use it as follows:

import { of } from "rxjs";
of(1, 2, 3).subscribe(  
  val => console.log(val),  
  err => console.log(err),  
  () => console.log("end")  
);

range

We can use range to create an Observable that emits a sequence of numbers within the specified range.

It takes 3 optional arguments, which are the start, which defaults to 0. The number of integers to generate, which defaults to undefined and the scheduler to use, which defaults to undefined .

For example, we can use it to create an Observable which emits number 1 to 20 as follows:

import { range } from "rxjs";
const numbers = range(1, 20);  
numbers.subscribe(x => console.log(x));

throwError

Creates an Observable that only emits an error notification.

It takes up to 2 arguments. The first is the error to emit. The second is an optional scheduler argument to let us choose the scheduler. It defaults to undefined .

We can use it as follows:

import { throwError } from "rxjs";
const numbers = throwError("error");  
numbers.subscribe(() => {}, err => console.log(err));

We subscribed to the error notification in the second argument.

timer

timer creates an Observable that starts emitting values after a specified time and emit ever-increasing number after a specified interval thereafter.

The first argument is the time that the Observable starts emitting, which defaults to 0. The number is in milliseconds.

The second argument is the period of emitting values which defaults to undefined . The number is in milliseconds.

The last argument is the scheduler to use, which defaults to undefined .

For example, we can create an Observable to emit values after 2 seconds, then every second thereafter by writing:

import { timer } from "rxjs";
const numbers = timer(2000, 1000);  
numbers.subscribe(x => console.log(x));

iif

Let us create an Observable that decides which Observable will be subscribed to at subscribe time.

It takes up to 3 arguments. The first is the condition for which Observable to be chosen. The 2nd and 3rd arguments are the Observable that are chosen when the condition is true and false respectively.

For example, we can use it as follows:

import { iif, of } from "rxjs";
let wantFoo;  
const fooBar = iif(() => wantFoo, of("foo"), of("bar"));
wantFoo = true;  
fooBar.subscribe(val => console.log(val));
wantFoo = false;
fooBar.subscribe(val => console.log(val));

In the code above, if wantFoo is true , when of('foo') is subscribed. Otherwise, of('bar') is subscribed.

We can create Observables that handle DOM or Node.js events with the fromEvent creation operator.

of operator lets us create Observables from any list of objects.

throw only throws an error and does nothing else.

generate , interval , and range let us create Observables that emit number ranges.

timer lets us create timed Observables and iif lets us create conditional Observables.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *