Rxswift: Observable.combineLatest with an empty collection does not complete.

Created on 19 Apr 2017  路  9Comments  路  Source: ReactiveX/RxSwift

Short description of the issue:

Observable.combineLatest(Collection) with an empty Collection does not complete.

Expected outcome:

The Observable completes immediately.

What actually happens:

The Observable does not complete.

Self contained code example that reproduces the issue:

let disposeBag = DisposeBag()

Observable.combineLatest([Observable<String>]()) { $0 }
    .subscribe(onCompleted: { print("completed!") })
    .addDisposableTo(disposeBag)

// never prints "completed!"

RxSwift/RxCocoa/RxBlocking/RxTest version/commit

3.4.0

Platform/Environment

  • [x] iOS
  • [ ] macOS
  • [ ] tvOS
  • [ ] watchOS
  • [ ] playgrounds

How easy is to reproduce? (chances of successful reproduce after running the self contained code)

  • [x] easy, 100% repro
  • [ ] sometimes, 10%-100%
  • [ ] hard, 2% - 10%
  • [ ] extremely hard, %0 - 2%

Xcode version:

8.3.1

:warning: Fields below are optional for general issues or in case those questions aren't related to your issue, but filling them out will increase the chances of getting your issue resolved. :warning:

Installation method:

  • [ ] CocoaPods
  • [x] Carthage
  • [ ] Git submodules

I have multiple versions of Xcode installed:
(so we can know if this is a potential cause of your issue)

  • [x] yes (8.3.1, 8.2.1)
  • [ ] no

Level of RxSwift knowledge:
(this is so we can understand your level of knowledge
and formulate the response in an appropriate manner)

  • [ ] just starting
  • [ ] I have a small code base
  • [x] I have a significant code base

Most helpful comment

Fix for this is pushed in develop branch. We'll release this in a couple of days.

All 9 comments

Hi @scottrhoyt ,

yeah, I think we need to improve that behavior. I'm still not sure what is the best way to handle this. Completing the sequence seems the most probably candidate.

Were you using this to wait for aggregate network requests? What was the use case?

@kzaher similar.

My use case is waiting for an aggregation of local queries (in this case, querying a user's contacts). I filter some data (an array) before mapping it to an array of observables that I combine into an observable of an array. The completion of this combined observable has a side effect of stopping a loading indicator. I noticed that when the filtering process produced an empty array, the resulting combined observable would never complete and my loading indicator would never stop.

It was fairly simple to workaround by mapping to an empty observable when the array of observables is empty, but the behavior was counterintuitive to me.

@scottrhoyt yeah, agreed. We'll fix this somehow.

We have the same problem with zip operator. Combine latest is more straightforward to solve, but we'll figure something out. I would like to investigate first how other implementations are behaving in these cases.

I occurred this situation when I use zip , hope it will fix soon

Thanks @kzaher. Let me know if you need any additional feedback.

Fix for this is pushed in develop branch. We'll release this in a couple of days.

I tried to use Observable.empty() in Zip operator. The completion block wouldn't execute in that case. I tried a sort of hack
Observable<Response>.empty().ifEmpty(default: Response(statusCode: 0,data: Data.cs_emptyValue()))
My expected value of Observable is Response. (Maya Response object) I gave it empty data and status code 0 with Observable type . Yes ! it worked.
@kzaher not sure if this is the correct approach, but this looks like a solution in my case. As I have dynamic observables to be called.

I run into this issue while testing view models using RxCocoa. In my case I have something like

let search = Variable("")
search.flatMapLatest { query -> Observable<Result> in
guard !query.isEmpty else {
return .empty()
}
return ... //Some observable

Was this page helpful?
0 / 5 - 0 ratings