Creational Operators

Get introduced to the creational operators that wrap different data sources into Observables.

We'll cover the following

So far, we have encountered some RxJS operators that we used to wrap different data sources to create Observables, like from and of, but there is more to it. In this section, you will be introduced to the most commonly used creational operators. In the end, we will provide a documentation reference for some other creational operators.



from

The from operator can be used to wrap an array, a promise, or an iterable into an Observable. The code given below demonstrates how to wrap an array of strings into an Observable. Every new subscriber will be able to consume all the data from the data source.

demo
main.js
const { from } = require('rxjs');
const DATA_SOURCE = [ 'String 1', 'String 2', 'Yet another string', 'I am the last string' ];
const observable$ = from(DATA_SOURCE)
observable$.subscribe(console.log)



of

of is another creational operator that creates Observable from a sequence of data. The difference between from and of is that from creates an Observable from an iterable, which can be an array.

Notice how the entire array is emitted in the first example, when provided as a single parameter to the of operator, compared to the sequence of items emitted in the second example.

demo
main.js
const { of } = require('rxjs');
const DATA_SOURCE = [ 'String 1', 'String 2', 'Yet another string', 'I am the last string' ];
const observableArray$ = of(DATA_SOURCE)
console.log("Array data source")
observableArray$.subscribe(console.log)
console.log("\n")
console.log("Sequence data source")
const observableSequence$ = of('String 1', 'String 2', 'Yet another string', 'I am the last string')
observableSequence$.subscribe(console.log)



range

range is a very useful operator that emits all numbers from a given range in a sequence. This is very useful if we want to iterate an array in a reactive fashion.

The following example demonstrates the creation of a range, which includes the starting and ending index of the given array.

demo
main.js
const { range } = require('rxjs');
const data = ['item 1', 'item 2', 'item 3']
const observableRange$ = range(0, data.length)
observableRange$.subscribe(index => console.log(data[index]))



Interval

As the name suggests, this operator is able to emit values at regular intervals. We will use this operator later in this course to show interactive timed notifications, but for now, let’s stick with a simple example.

Note: We need to unsubscribe from the Observable after a specific time (one second in this case) since the Observable will constantly produce new values every 100ms.

demo
main.js
const { interval } = require('rxjs');
const fastObservable$ = interval(100)
const subscription = fastObservable$.subscribe(() => console.log('100ms have passed'))
setTimeout(() => {
subscription.unsubscribe();
console.log('1 second has passed');
}, 1000)



Timer

Using the previous example with interval as a starting point, suppose that we would want the values to start emitting at regular intervals only after one second has passed. We can achieve that with the timer operator. The following example indicates that the Observable will start producing values after 1000ms and will produce values at regular intervals of 100ms.

This operator can be useful in some cases where you would want values produced over regular intervals, which will start after a certain amount of time has passed.

demo
main.js
const { timer } = require('rxjs');
const fastObservable$ = timer(1000, 100)
const subscription = fastObservable$.subscribe(() => console.log('100ms have passed'))
setTimeout(() => {
subscription.unsubscribe();
console.log('1 second has passed');
}, 1000)



defer

defer is an operator that takes a function as an argument and executes it only when an Observer subscribes to it. This is very useful for time-related operations, e.g., getting the current time of execution.

The following examples illustrate the usage of defer when the function that is passed to the Observable doesn’t return anything and when it returns an Observable, represented by Example 1 and Example 2, respectively. Remember, the function passed to defer must return an Observable in order to remain within the concept of pure functions.

demo
main.js
const { defer, of } = require('rxjs');
// Example 1
const functionToBeExecutedOnSubscribe = () => console.log('exectuing now')
const observable1$ = defer(functionToBeExecutedOnSubscribe)
observable1$.subscribe()
// Example 2
const functionToBeExecutedOnSubscribeReturnsObservable = () => of('val1', 'val2')
const observable2$ = defer(functionToBeExecutedOnSubscribeReturnsObservable)
observable2$.subscribe(console.log)



fromEvent

The most useful operator when building complex SPAs is fromEvent. You would use this operator to wrap mouse or keyboard events into Observables, as shown below:

const keysDown$ = fromEvent(document, 'keydown')
keysDown$.subscribe(console.log)

These creational operators cover most of your needs while applying the reactive paradigm to your JS application. However, there are additional creational operators that you may find useful.

You can find them here, along with other RxJS operators, which we will discuss in the next lessons.