Rxjs: toArray() after groupBy() produces empty groups

Created on 15 Sep 2016  路  5Comments  路  Source: ReactiveX/rxjs

RxJS version: 5.0.0-beta.12

Code to reproduce: https://jsbin.com/bovicux/20/edit?js,console

Expected result: an array with groups of items

Actual result: an a array of empty groups

Additional information:

Most helpful comment

@adriano-fonseca this was a stop-gap measure, and is superseded with the addition of a subject selector to groupBy. Now you can do this to guarantee inner groups replay events emitted to groups before a group is subscribed:

Observable
  .of(0, 1, 2, 3)
  .groupBy(x => x % 2 ? 'odd' : 'even', null, null, () => new ReplaySubject())
  .delay(100) // artificially inject some delay to ensure inner events are emitted to groups before the groups are emitted
  .subscribe((group) => group.subscribe(console.log.bind(console, group.key)));
// should print:
// even: 0
// even: 2
// odd: 1
// odd: 3

All 5 comments

@titonobre this is working as expected. The GroupedObservables emitted by groupBy are notified of events as they occur, but they don't replay them after the fact. The toArray after groupBy queues all the GroupedObservables into a list, but only emits the list when groupBy completes, at which point all the inner groups have already been notified of events.

You can multicast each GroupedObservable with a ReplaySubject if you want the groups to replay the events to future subscribers after the fact:

Rx.Observable
  .from(events)
  .groupBy(e => e.year)
  .map(group => {
    const groupReplayed = group.multicast(new Rx.ReplaySubject());
    const connection = groupReplayed.connect(); // connect immediately so we don't miss events
    // Wrap with `using` so `connection` is unsubscribed when the `using` subscription is unsubscribed
    const groupedWithResource = Rx.Observable.using(() => connection, () => groupReplayed);
    // copy over the key so subscribers think we're a real GroupedObservable
    groupedWithResource.key = group.key;
    return groupedWithResource;
  })
  .toArray()
  .subscribe(
  groups => groups.forEach(group => printGroup(group)),
  console.error,
  print('complete demo 3')
);

Oops! My bad.
Thank you.

I am try to use this approach, but observable does not have key. I am using 5.1.0. And this line breaks. Any help?

groupedWithResource.key = group.key;

@adriano-fonseca this was a stop-gap measure, and is superseded with the addition of a subject selector to groupBy. Now you can do this to guarantee inner groups replay events emitted to groups before a group is subscribed:

Observable
  .of(0, 1, 2, 3)
  .groupBy(x => x % 2 ? 'odd' : 'even', null, null, () => new ReplaySubject())
  .delay(100) // artificially inject some delay to ensure inner events are emitted to groups before the groups are emitted
  .subscribe((group) => group.subscribe(console.log.bind(console, group.key)));
// should print:
// even: 0
// even: 2
// odd: 1
// odd: 3

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

giovannicandido picture giovannicandido  路  4Comments

shenlin192 picture shenlin192  路  3Comments

matthewwithanm picture matthewwithanm  路  4Comments

LittleFox94 picture LittleFox94  路  3Comments

benlesh picture benlesh  路  3Comments