结合两个Observable <void> s

时间:2015-10-31 20:38:22

标签: swift reactive-programming rx-swift

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

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(或{{1没有发出任何Error事件。)如果Next完成但doA()错误,我希望doB()发出doIt()然后完成。

感觉我应该使用.BFailedzip,但我不知道如果我这样做,如何知道哪个序列失败了。我也非常确定combineLatest是解决方案的一部分,但我不确定将其放在何处。

-

正如我想的那样,我可以按顺序发出呼叫。那甚至可能更好......

IE:

catchError

感谢您的帮助。

3 个答案:

答案 0 :(得分: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() doc。

  

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

答案 1 :(得分: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()运算符基本上将OnNextOnErrorOnCompleted通知的T类型OnNext通知变为Notification<T>通知类型.Zip(...)的可观察量。然后,您可以p.shutdown()这些并检查您所需的条件。

答案 2 :(得分:0)

I seem to have found an answer myself... Admittedly this solution doesn't wait for the complete message from either doA() or doB(). Instead it emits the Result object on the onNext signal, but since these are network calls, there will only be one onNext before the completion anyway. Maybe thinking I had to wait for the complete was the thing that was making it hard for me to understand.

func doIt() -> Observable<Result> {
    return doA().flatMap {
        return doB().map { 
            .Success 
        }
        .catchError {
            just(.BFailed)
        }
    }
}