Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 RxJS Does the Zip Operator have a limit on arguments?

I'm mystified right now on what's causing this bug. I am trying to zip the result of 7 Observables like:

var zipped$ = Observable.zip(
    Observable.of({prop1:1}),
    Observable.of({prop2:2}),
    Observable.of({prop3:3}),
    Observable.of({prop4:4}),
    Observable.of({prop5:5}),
    Observable.of({prop6:6}),
    Observable.of({prop7:7})
);

And then merge them with mergeAll() and reduce() like:

var reduced$ = zipped$.mergeAll().reduce((acc,val) => Object.assign({},acc,val));
reduced$.subscribe(final => console.log(final));

But I get this error: "property 'reduce' does not exist on type '{}'"

To add to the confusion:

If I use 6 values, it works fine.

If the observables all return primitives, it works fine.

if I add this function as the final argument in my zip:

function(...args: any[]) {
    // I have no ieda why I need this hack, but the zip fails without it.
    return args;
}

it works fine.

Is this a bug in RxJS? Am I missing something about the zip implementation? Is this an angular compiler thing?? No amount of searching docs has revealed a limit on the number of arguments to zip. Any insight is appreciated.

Thanks

EDIT: for any one else who finds this.

the best work around is to just stick the observables in an array and feed it as a single argument like:

var zipped$ = Observable.zip(...[
    Observable.of({prop1:1}),
    Observable.of({prop2:2}),
    Observable.of({prop3:3}),
    Observable.of({prop4:4}),
    Observable.of({prop5:5}),
    Observable.of({prop6:6}),
    Observable.of({prop7:7})]);

which also works fine. EDIT: the array feed stopped working, now need to use spread operator and array.

like image 794
bryan60 Avatar asked Aug 04 '17 18:08

bryan60


Video Answer


1 Answers

A lot of things had changed since 2017, the rxjs documentation nowadays is very good and covers pretty much everything that one may desire.

Now let's dive into the question.

First thing first the old zip operator (which can be found here: old zip ) is now deprecated in favor of the new zip (which can be found here: zip)

The main difference is that the old one was a chainable operator that was used like so (later on it became pipe-able):

of(1).pipe( zip(of(2)),map(([a,b]) => ({a,b}))).subscribe(x => console.log(x) // {a:1, b:2})

While the new one is a creational operator and is used like so:

zip(of(1),of(2)).pipe(delay(1000),map(([a,b]) => ({a,b}))).subscribe(x => console.log(x) // {a:1, b:2})

Now about the question, there is no limitation to the number of observables that you can pass in the zip opertor, for exmaple the following snippet will work

let arr = (new Array(100)).fill(false).map((x,i)=> of({[`key${i}`]:i}))
zip(...arr).pipe(
  mergeAll(),
  reduce((acc,val) => Object.assign({},acc,val)),
)

However if you are using typescript and are passing more than 6 observables of different types you will lose the typeings and autocompletion.

like image 108
Християн Христов Avatar answered Nov 14 '22 22:11

Християн Христов