I don't understand the difference between these two chunks of code, I would expect identical behavior. The first one has a groupBy and mergeMap after the switchMap. The second one has them inside the switchMap.
const arraySubject = new Subject();
arraySubject.pipe(
switchMap((arr) => from(arr)),
groupBy((elem) => elem.type),
mergeMap((group) => group.pipe(toArray()))
).subscribe((arrGroups) => {
// nothing gets logged
})
arraySubject.next([{name: 'Bill', type: 'user'}, {name: 'Jane', type: 'admin'}, {name: 'John', type: 'user'}, {name: 'Ann', type: 'admin'}])
Now if I put the groupBy and mergeMap in the pipe of the from(arr) everything works.
const arraySubject = new Subject();
arraySubject.pipe(
switchMap((arr) =>
from(arr).pipe(
groupBy((elem) => elem.type),
mergeMap((group) => group.pipe(toArray()))))
).subscribe((arrGroups) => {
arrGroups === [
{name: 'Bill', type: 'user'},
{name: 'John', type: 'user'}
], [
{name: 'Jane', type: 'admin'},
{name: 'Ann', type: 'admin'}] //true
})
arraySubject.next([{name: 'Bill', type: 'user'}, {name: 'Jane', type: 'admin'}, {name: 'John', type: 'user'}, {name: 'Ann', type: 'admin'}])
In the first chunk of code I just guessed that groupBy would simply group the elements by type then pass two observables (in this case) to the mergeMap which will then convert those two observables to an Array. In my opinion the second piece of code would do the exact same thing? But for some reason the first one does not work. Why is the first one not working, and the second one working?
The issue here is that your
arraySubject
never completes. SotoArray()
doesn't know when to emit the collected values.In the second example,
from(arr)
is the source (instead of the subject) which does complete and letstoArray()
emit the buffered values.Update 01:
In short: yes, exactly this.
To expand on that a bit:
is the similar to (I say similar, since one is "hot" and one is "cold". If nobody is subscribed to the subject when it emits, the value is lost).
That is, when you pass an array to
from()
, it will emit each element of the array and then signal the the entire array's elements have been emitted by emitting acomplete
A Subject must be completed explicitly, since it doesn't know if you plan to continue emitting (via
subject.next()
) some time in the future. It must assume it may still get a value until it's explicitly told that it will not.