RxSwift:在onNext之后调用onCompleted仅传递已完成的事件

时间:2019-07-30 21:30:52

标签: rx-swift

我将一些旧的完​​成块代码包装在Observable中。它将发出一个事件(下一个或错误),然后完成。问题在于调用onNext(), onCompleted()仅将完成的事件发送给观察者。为什么next事件没有传递?

更新:人员流实际上按预期工作。问题出在下一个流,filteredPeople。内部完成事件将传递给它,而我只是返回它,它终止了流。

我需要从内部流中过滤出completed个事件。

let people = Observable<Event<[Person]>>()
    .flatMapLatest {
        return fetchPeople().asObservable().materialize()
    }
    .share()

// this is bound to a search field
let filterText = PublishSubject<String>()

let filteredPeople = Observable.combineLatest(people, filterText) { peopleEvent, filter in

    // this is the problem. the completed event from people is being returned, and it terminates the stream
    guard let people = peopleEvent.element else { return peopleEvent }

    if filterText.isEmpty { return .next(people) }

    return .next(people.filter { ... })
}

func fetchPeople() -> Single<[Person]> {
    return Single<[Person]>.create { observer in
        PeopleService.fetch { result in
            switch result {
            case .success(let people):
                observer(.success(people))
            case .failure(let error):
                observer(.error(error))
            }
        }

        return Disposables.create()
    }
}

filteredPeople.subscribe(
    onNext: { event in
        // ?! doesn't get called
    },
    onCompleted: {
        //  we get here, but why?
    },
    onError: {event in
        ...
    }).disposed(by: disposeBag)

2 个答案:

答案 0 :(得分:2)

您尚未发布导致问题的代码。下面的代码按预期工作:

struct Person { }

class PeopleService {
    static func fetch(_ result: @escaping (Result<[Person], Error>) -> Void) {
        result(.success([]))
    }
}

let disposeBag = DisposeBag()

func fetchPeople() -> Single<[Person]> {
    return Single<[Person]>.create { observer in
        PeopleService.fetch { result in
            switch result {
            case .success(let people):
                observer(.success(people))
            case .failure(let error):
                observer(.error(error))
            }
        }

        return Disposables.create()
    }
}

let people = Observable<Void>.just(())
    .flatMapLatest { _ in
        return fetchPeople().asObservable().materialize()
    }
    .share()

people.subscribe(
    onNext: { event in
        print("onNext does get called")
        print("in fact, it will get called twice, once with a .next(.next([Person])) event")
        print("and once with a .next(.completed) event.")
    },
    onCompleted: {
        print("this prints after onNext gets called")
    })
    .disposed(by: disposeBag)

答案 1 :(得分:0)

我通过从内部流中过滤出已完成的事件来修复它。我不确定这是正确的方法,但是我想不出更好的解决方案。

let people = Observable<Event<[Person]>>()
    .flatMapLatest {
        return fetchPeople()
            .asObservable()
            .materialize()
            // Our work is done, but don't end the parent stream
            .filter { !$0.isCompleted }
    }
    .share()