of([1,2,3]).subscribe(console.log)
prints:[1,2,3]
But:
of([1,2,3]).pipe(concatAll()).subscribe(console.log)
prints:
1
2
3
Why the above happens? Why adding concatAll() emits the elements of the array one by one? Isn't this somehow the opposite of what the word concat means?
I feel that concatAll() acts differently depending on the input.
Consider also this:
from([of(1),of(2),of(3)]).pipe(concatAll()).subscribe(console.log)
It will again print:
1
2
3
So of([1,2,3]).pipe(concatAll()) == from([of(1),of(2),of(3)]).pipe(concatAll())
But of([1,2,3]) != from([of(1),of(2),of(3)]) because subscribing to the latter will print:
Observable { _isScalar: false, _subscribe: [Function] }
Observable { _isScalar: false, _subscribe: [Function] }
Observable { _isScalar: false, _subscribe: [Function] }
The right side of the above equality is pretty clear to me, but where is documented that concatAll() should emit all the values of the array separately, acting like a pipeable from?
All the operators that deal with higher-order observable operators, perform the same conversion that RxJS's from operator does.
that is:
mergeMap(_ => ([1,2,3]))
Is basically the same as
mergeMap(_ => from([1,2,3]))
That works the same when merging/switching/concatenating promises and other iterables.
The difference you're seeing in behaviour is also attributed to the fact that from creates a new observable, while the higher-order observable operators tend to create a new observables and define behaviour around how those observables are subscribed to.
so concatAll is adding extra behaviour.
Finally, just because two things have similar outputs for a given example, doesn't mean they're doing the same thing under the hood.
of([1,2,3]).pipe(concatAll()) and from([of(1),of(2),of(3)]).pipe(concatAll()) describe two very different set of behaviours that in (this case) give you the same output to the console.
The first emits an array and has that array turned into a stream of numbers by concatAll(). The second emits three observables, and has has concatAll() subscribe to each only when the previous one completes. They complete after emitting just one number.
You can see the distinction clearly with your second example:
of([1,2,3]) and from([of(1),of(2),of(3)])
The first emits and array, the second emits three observables. That hasn't changed.
concat([1,2,3]), &&
concat(of(1), of(2), of(3))
Emit the same output again as well.
According to the documentation, the buffer transform will wait for a delay before emitting any values. What I'd like is to get the current value immediately, then only update every X seconds.
I've not been able to achieve this with rxjs yet. The closest I've come is to bind the observable then use a setTimeout function to rebind after the buffer timeout occurs. This has a side effect of clearing the current value for those X seconds before emitting the current values.
Any ideas?
Thanks!
Assuming by "current value immediately" you mean "first value as soon as it emits", you can buffer on the second element to the last, and merge in the first:
// source$: Observable<T>
const pub_source$ = source$.publish();
Observable.merge(
pub_source$.take(1).map(first => [first]),
pub_source$.skip(1).buffer(Observable.interval(X))
);
pub_source$.connect();
The source needs to be cold so that take(1) and skip(1) relate to the same element, so we use publish. The first element is also wrapped to keep the output type T[] consistent.
There's an easier way using the zip operator, see lightbulb note in learnrxjs
Combined with interval or timer, zip can be used to time output from another source!
// Useful for slow source that emits at around the same rate as interval
// but suffers back-pressure with fast-emitting source
const interval = 1000
const output = Observable.zip(source, Observable.timer(0, interval))
.map(x => x[0])
The Observable.timer 'regulates' the output from source. Note, timer's first parameter sets the delay for the first emit.
Working example: CodePen
Footnote
I just realized this will create back-pressure (build-up of un-emitted values) if you have a lot of events per second, so buffer is the better way to go with a fast emitting source.
// Buffered version for fast source
const output2 = source.buffer(Observable.timer(0, interval))
.filter(x => x.length) // filter out empty buffer emits
.flatMap(x => Observable.from(x)) // optional, converts array back to single emits
Is the only difference between Observable.of and Observable.from the arguments format? Like the Function.prototype.call and Function.prototype.apply?
Observable.of(1,2,3).subscribe(() => {})
Observable.from([1,2,3]).subscribe(() => {})
It is important to note the difference between of and from when passing an array-like structure (including strings):
Observable.of([1, 2, 3]).subscribe(x => console.log(x));
would print the whole array at once.
On the other hand,
Observable.from([1, 2, 3]).subscribe(x => console.log(x));
prints the elements 1 by 1.
For strings the behaviour is the same, but at character level.
Not quite. When passing an array to Observable.from, the only difference between it and Observable.of is the way the arguments are passed.
However, Observable.from will accept an argument that is
a subscribable object, a Promise, an Observable-like, an Array, an iterable or an array-like object to be converted
There is no similar behaviour for Observable.of - which always accepts only values and performs no conversion.
One line Difference :
let fruits = ['orange','apple','banana']
from : Emit the items one by one of array. For example
from(fruits).subscribe(console.log) // 'orange','apple','banana'
of : Emit the whole array at once. For example
of(fruits).subscribe(console.log) // ['orange','apple','banana']
NOTE: of operator can behave as from operator with spread operator
of(...fruits).subscribe(console.log) // 'orange','apple','banana'
Another interesting fact is Observable.of([]) will be an empty array when you subscribe to it.
Where as when you subscribe to Observable.from([]) you wont get any value.
This is important when you do a consecutive operation with switchmap.
Ex:
In the below example, I am saving a job and then sites, and then comments as a stream.
.do((data) => {
this.jobService.save$.next(this.job.id);
})
.switchMap(() => this.jobService.addSites(this.job.id, this.sites)
.flatMap((data) => {
if (data.length > 0) {
// get observables for saving
return Observable.forkJoin(jobSiteObservables);
} else {
**return Observable.of([]);**
}
})).do((result) => {
// ..
})
.switchMap(() => this.saveComments())
....
if there's no site to save, ie; data.length = 0 in addSite section, the above code is returning Observable.of([]) and then goes to save comments. But if you replace it with Observable.from([]), the succeeding methods will not get called.
rxfiddle
of will emit all values at once
from will emit all values one by one
of with spread operator = from operator
from: Create observable from array, promise or iterable. Takes only one value. For arrays, iterables and strings, all contained values will be emitted as a sequence
const values = [1, 2, 3];
from(values); // 1 ... 2 ... 3
of: Create observable with variable amounts of values, emit values in sequence, but arrays as single value
const values = [1, 2, 3];
of(values, 'hi', 4, 5); // [1, 2, 3] ... 'hi' ... 4 ... 5
from returns notification in chunks i.e. one by one.
for eg: from("abcde") will return a => b => c => d => e
of returns complete notification.
for eg: of("abcde") will return abcde.
https://stackblitz.com/edit/typescript-sckwsw?file=index.ts&devtoolsheight=100
The from operator takes source of events. from(source)
let array = [1,2,3,4,5]
from(array); //where array is source of events, array[of events]
let promise = new Promise(function(resolve, reject) {
// executor (the producing code, "singer")
});
from(promise); //where promise is source of event, promise(of event)
let observable = Observable.create(function(observer) {
observer.next(1);
observer.next(2);
observer.next(3);
observer.next(4);
observer.next(5);
observer.complete();
});
from(observable); // where obsservable is source of events.
The of operator takes intividual events. of(event1, event2, event3)
of(1,2,3,4,5); // where 1,2,3,4,5 are individual events
I found it easier to remember the difference when the analogy with .call / .apply methods came into my mind.
You can think of it this way:
normally, all arguments, that are passed separately (separated by comma), are also emitted separately, in the order they were passed. of() just emits all arguments one by one as they are (like .call method passes arguments to the function it was called on)
from() is like .apply in a sense that it can take an array of values as an argument, and convert array elements into separate arguments, separated by comma.
So, if you have an array and want each element to be emitted separately, you can use from() or get the same behavior by using of() with spread operator, like of(...arr).
It's bit more complicated then that (from can also take observables) but with this analogy it will probably be easier to remember the main difference.
Yes it is true that of will result in an output in single go and from will happen one at a time. But there is more difference related to number of arguments and type of arguments.
You can pass any number of arguments to the Of. Each argument emitted separately and one after the other. It sends the Complete signal in the end.
However you can send only one argument to the from operator and that one argument should be a type of
an Array,
anything that behaves like an array
Promise
any iterable object
collections
any observable like object
For example you can send a raw object like
myObj={name:'Jack',marks:100}
to of operator to convert to Observable.
obj$:Observable<any> = of(myObj);
but you can not send this raw object myObj to from operator simply because it is not iterable or array like collection.
for more detail : visit here
from operator may accept one of
promises
iterable
arrays
observable
from emits each individual item from the observable , can also do conversions.
of operator takes in the raw value and emits the value from the observable.
import {from, Observable, of} from 'rxjs';
const ofObs = of([1,2,3]);
const fromObs = from([2,3,4]);
const basicObs = Observable.create(observer=>{
observer.next(100);
observer.next(200);
observer.next(300);
})
const promise = new Promise((resolve,reject)=>{
resolve(100);
})
const array = [1,2,3];
const iterbale = "Dhana";
// const myObs = from(ofObs);//possible and can emit individual item value everytime 1, then ,2 , then 3
// const myObs = from(fromObs);//possbile and can emit individual item value everytime 1, then ,2 , then 3
// const myObs = from(basicObs);//possbile and can emit individual item value everytime 100, then ,200 , then 300
const myObs = from(promise);//possible can emit value 100
// const myObs = array(promise);//possible and can emit individual item value everytime 1, then ,2 , then 3
// const myObs = iterable(promise);//possible and can emit individual item value everytime D then h then a then n then a
myObs.subscribe(d=>console.log(d))
import {from, of} from 'rxjs';
const basicOf1 = of([1,2,3,4,5,6]) // emits entire array of events
const basicfrom1 = from([1,2,3,4,5,6]) //emits each event at a time
const basicOf2 = of(1,2,3,4,5,6) // emits each event at a time
// const basicfrom2 = from(1,2,3,4,5,6) //throws error
//Uncaught TypeError: number is not observable
const basicOf3 = of(...[1,2,3,4,5,6]) // emits each event at a time
const basicfrom3 = from(...[1,2,3,4,5,6]) //throws error
//Uncaught TypeError: number is not observable
basicOf3.subscribe(d=>console.log(d))
Here is the link to codepen
In rxjs5 doc, it mentions 'To reduce polymorphism and get better performance out of operators, some operators have been split into more than one operator'. What does it actually mean and how to use the mergeMapTo operator?
From the docs, mergeMapTo:
It's like mergeMap, but maps each value always to the same inner Observable.
I see mergeMapTo as a shortcut to always output the same value. mergeMapTo doesn't care about the source value.
Also from the docs:
Maps each source value to the given Observable innerObservable
regardless of the source value, and then merges those resulting
Observables into one single Observable, which is the output
Observable.
You'll see that mergeMap takes a function while mergeMapTo takes a value:
An example with mergeMap (we're transforming values):
Rx.Observable.of(1, 2, 3).mergeMap(x =>
Rx.Observable.interval(1000).map(i => x+i)
);
While using mergeMapTo we can take values from a stream and always output the same value (also transforming, but always to the same value):
Rx.Observable.of(1, 2, 3).mergeMapTo(10);
At the moment zip will only produce a value whenever all of the zipped observable produces a value. E.g. from the docs:
Merges the specified observable sequences or Promises into one
observable sequence by using the selector function whenever all of the
observable sequences have produced an element
I'm looking for an observable which can sort of zip an observable but will produce an array of sequence of the zipped observable wherein it doesn't matter if all produces a value..
e.g. lets say i have tick$, observ1, observ2.. tick$ always produce value every x secs.. while observ1 and observ2 only produces from time to time..
I'm expecting my stream to look like
[tick, undefined, observ2Res],
[tick, undefined, undefined],
[tick, observ1Res, observ2Res]
...
...
its not combine latest, given that combine latest takes the latest value of a given observable.
I believe buffer (or maybe sample) might get you on the right track. The buffer method accepts an Observable that's used to define our buffer boundaries. The resulting stream emits any items that were emitted in that window (example stolen from RXJS docs for buffer):
var source = Rx.Observable.timer(0, 50)
.buffer(function () { return Rx.Observable.timer(125); })
.take(3);
var subscription = source.subscribe(x => console.log('Next: ', x));
// => Next: 0,1,2
// => Next: 3,4,5
// => Next: 6,7
So we now have a way to get all of a stream's emitted events in a certain time window. In your case, we can use tick$ to describe our sampling period and observ1 and observ2 are our underlying streams that we want to buffer:
const buffered1 = observ1.buffer(tick$);
const buffered2 = observ2.buffer(tick$);
Each of these streams will emit once every tick$ period, and will emit a list of all emitted items from the underlying stream (during that period). The buffered stream will emit data like this:
|--[]--[]--[1, 2, 3]--[]-->
To get the output you desire, we can choose to only look at the latest emitted item of each buffered result, and if there's no emitted data, we can pass null:
const buffered1 = observ1.buffer($tick).map(latest);
const buffered2 = observ2.buffer($tick).map(latest);
function latest(x) {
return x.length === 0 ? null : x[x.length - 1];
}
The previous sample stream I illustrated will now look like this:
|--null--null--3--null-->
And finally, we can zip these two streams to get "latest" emitted data during our tick$ interval:
const sampled$ = buffered1.zip(buffered2);
This sampled$ stream will emit the latest data from our observ1 and observ2 streams over the tick$ window. Here's a sample result:
|--[null, null]--[null, 1]--[1, 2]-->