ReactiveX / rxdart

The Reactive Extensions for Dart

Home Page:http://reactivex.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CombineLatestStream emits data events after error events

TatsuUkraine opened this issue · comments

Not quite sure if it's expected behavior or an error.

So I have the following case.

I have StreamA and StreamB. Both wrapped with combine latest stream and simple string concat. StreamA emits and event 1, then StreamB emits 2. I get a data event like 1 2. Then StreamA emits an error event. The output of combine latest is an error event as well. All fine for now.

Now StreamB emits an event 3. Combine latest produces output like 1 3. Which is not quite expected)

So the question is - is described behavior is expected or it's an issue?

Here is a test case for this scenario with expected behavior (in my opinion) and it will fail

    final expectedResult = [
      '1 2',
      '3 4'
    ];
    final StreamController<int> controller1 = StreamController.broadcast(sync: true);
    final StreamController<int> controller2 = StreamController.broadcast(sync: true);

    final streamWithError = CombineLatestStream.combine2(
      controller1.stream,
      controller2.stream,
      (int aValue, int bValue) {
        return '$aValue $bValue';
      }
    );

    int count = 0;

    streamWithError.listen(
      expectAsync1((value) {
        expect(value, expectedResult[count++]);
      }, count: 2),
      onError: expectAsync2((Exception e, StackTrace s) {
        expect(e, isException);
      }, count: 1)
    );

    controller1.sink.add(1);
    controller2.sink.add(2);
    controller2.sink.addError(Exception());
    controller1.sink.add(3);
    controller2.sink.add(4);

With current implementation of CombineLatestStream expected result looks like this

final expectedResult = [
      '1 2',
      '3 2',
      '3 4',
    ];

That is expected behavior, in rxdart, the error event and data event are separated.
See https://github.com/ReactiveX/rxdart#rx-observables-vs-dart-streams

@hoc081098 sorry, but could you point where this describes as expected behavior? I'm curious because I would understand if after emitting 3 to controller1 combine latest doesn't generate any event, or generate error event that he go last time from controller2. Instead it generates a data event with last data event from controller1 nevertheless last event there was an error event

@hoc081098 I also curious, if it's an expected behavior , will it make sense to add another combine latest stream variant that will be matching test case that I provided? Or maybe update existing one with some flag like pauseOnError or errorAware ?

  • Combinelatest:

  • Zip

rxjs-zip

@hoc081098 yes, but there is nothing said about errors

My only concern in that scenario that strramB forces data event while streamA has an error event

will it make sense to add another combine latest stream variant that will be matching test case that I provided? Or maybe update existing one with some flag like pauseOnError or errorAware ?

Also curious what you think about this part of my question?

What's about materialize:

Rx.combineLatest2(streamA.materialize(), streamB.materialize(), (a, b) {
    if (a.isOnError || b.isOnError) {
      final eSt = (a.errorAndStackTrace ?? b.errorAndStackTrace)!;
      return Notification.onError(eSt.error, eSt.stackTrace);
    }
    if (a.isOnData && b.isOnData) {
      return Notification.onData('${a.requireData} ${b.requireData}');
    }
    return Notification.onDone();
}).dematerialize();