Creating an observable from iterable objects
We can create an observable from iterable objects using the from() method. An iterable in JavaScript can be an array (or an array-like object) or other iterates added in ES6 (such as Set() and map()). The from() method has the following signature:
Rx.Observable.from(iterable,[mapFunction],[context],[scheduler]);
Usually, you will pass only the first argument. Others arguments are optional; you can see them here:
- iterable: This is the iterable object to be converted into an observable (can be an array, set, map, and so on)
- mapFunction: This is a function to be called for every element in the array to map it to a different value
- context: This object is to be used when mapFunction is provided
- scheduler: This is used to iterate the input sequence
Now let's see some examples on how we can create observables from iterables.
To create an observable from an array, you can use the following code:
Rx.Observable
.from([0,1,2])
.subscribe((a)=>console.log(a));
This code prints the following output:
0
1
2
Now let's introduce a minor change in our code, to add the mapFunction argument to it, instead of creating an observable to propagate the elements of this array. Let's use mapFunction to propagate the double of each element of the following array:
Rx.Observable
.from([0,1,2], (a) => a*2)
.subscribe((a)=>console.log(a));
This prints the following output:
0
2
4
We can also use this method to create an observable from an arguments object. To do this, we need to run from() in a function. This way, we can access the arguments object of the function. We can implement it with the following code:
var observableFromArgumentsFactory = function(){
return Rx.Observable.from(arguments);
};
observableFromArgumentsFactory(0,1,2)
.subscribe((a)=>console.log(a));
If we run this code, we will see the following output:
0
1
2
One last usage of this method is to create an observable from either Set() or Map(). These data structures were added to ES6. We can implement it for a set as follows:
var set = new Set([0,1,2]);
Rx.Observable
.from(set)
.subscribe((a)=>console.log(a));
This code prints the following output:
0
1
2
We can also use a map as an argument for the from() method, as follows:
var map = new Map([['key0',0],['key1',1],['key2',2]]);
Rx.Observable
.from(map)
.subscribe((a)=>console.log(a));
This prints all the key-value tuples on this map:
[ 'key0', 0 ]
[ 'key1', 1 ]
[ 'key2', 2 ]
All observables created from this method are cold observables. As discussed before, this means it fires the same sequence for all the observers. To test this behavior, create an observable and add an Observer to it; add another observer to it after a second:
var observable = Rx.Observable.from([0,1,2]);
observable.subscribe((a)=>console.log('first subscriber receives => '+a));
setTimeout(()=>{
observable.subscribe((a)=>console.log('second subscriber receives => '+a));
},1000);
If you run this code, you will see the following output in your console, showing both the subscribers receiving the same data as expected:
first subscriber receives => 0
first subscriber receives => 1
first subscriber receives => 2
second subscriber receives => 0
second subscriber receives => 1
second subscriber receives => 2