ReactiveX / rxjs

A reactive programming library for JavaScript
https://rxjs.dev
Apache License 2.0
30.77k stars 3k forks source link

passing empty array into combineLatest closes subscription prematurely #7110

Open mkhodan opened 2 years ago

mkhodan commented 2 years ago

Describe the bug

Since rxjs 7 passing empty array into combineLatest and filling it later doesn't work as it immediately closes subscription even though we haven't subscribed yet.

Expected behavior

combineLatest waits until subscription and only then decides whether array is actually empty.

Reproduction code

e.g. this code worked in 6.6.2 but doesn't work anymore in 7.5.7

import { combineLatest, of } from 'rxjs';

let observables = [];

let result = combineLatest(observables);

for (let i = 0; i < 20; i++) {
  observables.push(of(i));
}

result.subscribe((numbers) => console.log(numbers));

please note that if we create array with at least 1 observable already there this works as expected in rxjs 7: let observables = [of(-1)];

Reproduction URL

https://stackblitz.com/edit/rxjs-6-daddo-playground-is6lgj?file=index.ts https://stackblitz.com/edit/rxjs-7-playground-3urg4j?file=index.ts

Version

7.5.7

Environment

No response

Additional context

No response

benlesh commented 8 months ago

This looks like it's happening because we're examining the array given prior to subscription, we're not assuming that someone might mutate the array after that.

The workaround for now would be to create the array prior to passing it to the combineLatest. If that doesn't work, you can always wrap the combineLatest in a defer.

import { combineLatest, of, defer } from "rxjs";

let observables = [];

let result = defer(() => combineLatest(observables))

for (let i = 0; i < 20; i++) {
  observables.push(of(i));
}

result.subscribe((numbers) => console.log(numbers));