RxSwift等待Observable完成

时间:2018-03-19 11:01:33

标签: swift reactivex

我是rxswift的新手,这是我的问题:

假设我有可观察的动作:Observable.of(“do1”,“do2”,“do3”)

现在这个observable映射到返回observable的函数:

let actions = Observable.of("do1", "do2", "do3")

func do(action: String) -> Observable<Result> {
       // do something
       // returns observable<Result>
}

let something = actions.map { action in return do(action) } ??? 

我如何等待do1先完成,然后执行do2,然后执行do3?

编辑:基本上我想实现动作的顺序执行。 do3等待do2结果,do2等待do1结果。

Edit2:我尝试过使用flatmap和subscribe,但所有操作都是并行运行。

4 个答案:

答案 0 :(得分:1)

  

我如何等待do1先完成,然后执行do2,然后执行do3?

我认为concatMap解决了这个问题。

假设我们有一些服务和一些我们需要对其执行的操作,例如我们想要验证和存储一些数据的后端。操作登录商店。如果我们未登录,我们无法存储任何数据,因此我们需要等待登录完成,然后才能处理任何商店操作

flatMapflatMapLatestflatMapFirst并行执行可观察对象时,concatMap会等待您的可观察对象完成后再继续。

import Foundation
import RxSwift
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

let service: [String:Observable<String>] = [
    "login": Observable.create({
        observer in
        observer.onNext("login begins")
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            observer.onNext("login completed")
            observer.onCompleted()
        })
        return Disposables.create()
    }),
    "store": Observable.create({
        observer in
        observer.onNext("store begins")
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
            observer.onNext("store completed")
            observer.onCompleted()
        })
        return Disposables.create()
    }),
]

// flatMap example
let observeWithFlatMap = Observable.of("login", "store")
    .flatMap {
        action in
        service[action] ?? .empty()
    }

// flatMapFirst example
let observeWithFlatMapFirst = Observable.of("login", "store")
    .flatMapFirst {
        action in
        service[action] ?? .empty()
    }

// flatMapLatest example
let observeWithFlatMapLatest = Observable.of("login", "store")
    .flatMapLatest {
        action in
        service[action] ?? .empty()
    }

// concatMap example
let observeWithConcatMap = Observable.of("login", "store")
    .concatMap {
        action in
        service[action] ?? .empty()
    }

// change assignment to try different solutions
//
// flatMap: login begins / store begins / store completed / login completed
// flatMapFirst: login begins / login completed
// flatMapLatest: login begins / store begins / store completed
// concatMap: login begins / login completed / store begins / store completed

let observable = observeWithConcatMap

observable.subscribe(onNext: {
    print($0)
})

答案 1 :(得分:0)

使用flatMapflatMapLatest。您可以在reactivex.io找到有关它们的更多信息。

答案 2 :(得分:0)

您可以通过在最终输出上调用flatMapsubscribeResult subscribe(on:)可观察序列。

actions
    .flatMap { (action) -> Observable<Result> in
        return self.doAction(for: action)
    }
    .subscribe(onNext: { (result) in
        print(result)
    })

func doAction(for action: String) -> Observable<Result> {
    //...
}

读:

答案 3 :(得分:0)

我只是面临同样的问题,终于找到了解决方案。 我希望我的设备会先断开连接,然后执行以下操作:

我只是创建像这样的功能

func disconnect(position: WearingPosition) -> Completable{
    print("test run")
    return Completable.create { observer in
          print("test run 2")    
          // Async process{
          //       observer(.complete)
          // }
                 
          return Disposables.create() 
    }
}

并使用类似:

self.disconnect(position: .left_wrist).andThen(Completable.deferred({
        
        return self.disconnect(position: .right_wrist)
        
    })).subscribe(onCompleted: {
        // do some things
        
    }) { (error) in
        print(error)
    }.disposed(by: self.disposeBag)

关键是“ Completable.deferred”的用法

我已经测试了印刷的“测试运行”