合并两个 Observable<Void>

6

我仍然是一个反应式新手,正在寻求帮助。

func doA() -> Observable<Void>
func doB() -> Observable<Void>

enum Result {
    case Success
    case BFailed
}

func doIt() -> Observable<Result> {

    // start both doA and doB. 
    // If both complete then emit .Success and complete
    // If doA completes, but doB errors emit .BFailed and complete
    // If both error then error

}

上述是我认为我想要的...初始功能doA()doB()包装了网络调用,因此它们都会发出一个信号,然后Complete(或Error而没有发出任何Next事件)。如果doA()完成但doB()出错,我希望doIt()发出.BFailed然后完成。

感觉应该使用zipcombineLatest,但我不确定如何知道哪个序列失败了。我也很确定catchError是解决方案的一部分,但我不确定应该把它放在哪里。

--

思考一下,我可以接受调用按顺序进行。这可能甚至更好...

即:

Start doA() 
    if it completes start doB() 
        if it completes emit .Success 
        else emit .BFailed.
    else forward the error.

感谢您的帮助。
谢谢。
3个回答

1
我相信 .flatMapLatest() 是您寻找的,可以将您的可观察请求链接在一起。
doFirst()
.flatMapLatest({ [weak self] (firstResult) -> Observable<Result> in
  // Assuming this doesn't fail and returns result on main scheduler,
  // otherwise `catchError` and `observeOn(MainScheduler.instance)` can be used to correct this
  // ...
  // do something with result #1
  // ...
  return self?.doSecond()
}).subscribeNext { [weak self] (secondResult) -> Void in
  // ...
  // do something with result #2
  // ...
}.addDisposableTo(disposeBag)

这里是 RxSwift 中 .flatMapLatest() 的文档。

将可观察序列的每个元素投射到一个新的可观察序列中,然后将可观察序列的可观察序列转换为仅从最近的可观察序列产生值的可观察序列。它是 map + switchLatest 操作符的组合。


0

非常抱歉我不知道Swift的语法,所以我用C#写了答案。这段代码应该可以直接翻译。

var query =
    doA
        .Materialize()
        .Zip(doB.Materialize(), (ma, mb) => new { ma, mb })
        .Select(x =>
            x.ma.Kind == NotificationKind.OnError
            || x.mb.Kind == NotificationKind.OnError
                ? Result.BFailed
                : Result.Success);

基本上,.Materialize() 操作符将类型为 T 的可观察对象的 OnNextOnErrorOnCompleted 通知转换为类型为 Notification<T> 的可观察对象的 OnNext 通知。然后,您可以使用 .Zip(...) 进行组合并检查所需的条件。


嗯...感谢您的回答,但是RxSwift没有materialize方法。至少目前还没有。 - Daniel T.

0

我已经学会了足够的RxSwift来回答这个问题...

func doIt() -> Observable<Result> {
    Observable.zip(
        doA().map { Result.Success },
        doB().map { Result.Success }
            .catch { _ in Observable.just(Result.BFailed) }
    ) { $1 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接