Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BehaviorSubject(1).toBlockingObservable.next.iterator.next() never completes #624

Closed
dvtomas opened this issue Dec 15, 2013 · 11 comments
Closed

Comments

@dvtomas
Copy link

dvtomas commented Dec 15, 2013

The scala expression

BehaviorSubject(1).toBlockingObservable.next.iterator.next()

never completes as of RxJava 0.15.1

To my understanding, it should simply return 1, since BehaviorSubject always has at least one value to provide. The fact that the following scala code correctly returns 1:

BehaviorSubject(1).take(1).toBlockingObservable.single

assures me about this assumption even more firmly. Is this a bug in the implementation, or do I misunderstand something?

Thank you, best regards,
Tomáš Dvořák

@akarnokd
Copy link
Member

This might be a bug in the underlying OperationNext L147 ignoring the very first value sent by the behavior subject.

@zsxwing
Copy link
Member

zsxwing commented Dec 16, 2013

I think you need the latest operator #59 (not implemented yet) rather than the next operator.

@zsxwing
Copy link
Member

zsxwing commented Dec 16, 2013

Each time you fetch an item from the iterator returned by next, you will receive the next incoming item in the Observable. In your example, when you fetch an item from the iterator, 1 has already been emitted, so it will be skipped.

@dvtomas
Copy link
Author

dvtomas commented Dec 17, 2013

I'm not sure I follow. Exactly at which point has 1 already been emitted? It has not been emitted after the toBlockingObservable call, because the second example still yields an item. So, somehow, the .next.iterator.next() must have "swallowed" one item, while the call to single manages not to swallow it and emit it as I'd expect. Could you please elaborate in more detail on what is the conceptual (not implementation) difference between the two? I'm still not convinced that the next call should skip the item provided by the BehaviorSubject.

Thank you very much.

@akarnokd
Copy link
Member

In the current RxJava version, when the code comes to BehaviorSubject(1).toBlockingObservable.next, the next operator subscribes to the behavior subject. The behavior subject immediately pushes down the value 1. In the next's Observer, there is a check to see if there is someone waiting for a value. Since the code above hasn't reached the .iterator().next() yet, which would indicate a demand for a value, the value 1 gets ignored. Now, the chain of call is returning and the iterator.next is executed, blocking for a value to arrive, which won't.

In BehaviorSubject(1).take(1).toBlockingObservable.single, the single operator uses toIterable internally, which buffers all values, including the very first 1, therefore, you'll see the 1.

Hope it clears things.

@dvtomas
Copy link
Author

dvtomas commented Dec 17, 2013

That clarifies a lot to me about the implementation. Furthermore, you have pointed me to the toBlockingObservable.toIterable operator, which is actually exactly what I have been looking for, but didn't found and tried to emulate with the .next.iterator() calls that in reality seem to have a slightly different semantics than I originally expected.

Thank you indeed,
Tomáš Dvořák

@benjchristensen
Copy link
Member

I confirmed that it does not work:

System.out.println(BehaviorSubject.create(1).take(1).toBlockingObservable().single());

System.out.println(BehaviorSubject.create(1).toBlockingObservable().next().iterator().next());

Someone will need to spend some time looking at OperationNext.

@benjchristensen
Copy link
Member

Interestingly this one works:

System.out.println(BehaviorSubject.create(1).toBlockingObservable().toIterable().iterator().next());

@akarnokd
Copy link
Member

akarnokd commented Jan 2, 2014

I had an explanation some time ago. Bottom line is that the next() can't work in this setup.

@benjchristensen
Copy link
Member

As of 0.20-RC3 these work:

System.out.println(BehaviorSubject.create(1).take(1).toBlocking().single());
System.out.println(BehaviorSubject.create(2).toBlocking().toIterable().iterator().next());

this still does not:

System.out.println(BehaviorSubject.create(3).toBlocking().next().iterator().next());

benjchristensen added a commit to benjchristensen/RxJava that referenced this issue Jul 24, 2014
@benjchristensen
Copy link
Member

A possible fix that allows the 3rd behavior is in #1501

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants