如何从RxSwift中的flatMapLatest返回不同的类型?

时间:2017-06-26 08:50:05

标签: swift rx-swift

我跟随RxSwift示例GitHub SignUp using Driver,最后得到了类似的东西。

我有一个执行身份验证的网络请求,并以这样的方式返回Observable<AuthenticationResult>

public enum AuthenticationResult {
    case canceled
    case usernameEmpty
    case passwordEmpty
    case invalidCredentials
    case granted(AccessToken)
    case other(Error)
}

// Authentication result status
let authenticationResult: Driver<AuthenticationResult>

authenticationResult = input.loginTaps.withLatestFrom(usernameAndPassword)
    .flatMapLatest({ (username, password) -> SharedSequence<DriverSharingStrategy, AuthenticationResult> in
        return API.authenticate(username: username, password: password, applicationScope: .property).trackActivity(signingIn).asDriver(onErrorJustReturn: .canceled)
    })
    .flatMapLatest({ (result) -> SharedSequence<DriverSharingStrategy, AuthenticationResult> in

        switch result {

        case .granted(_):
            // The closure is expecting a return value here that I don't have!
            let portfoliosNavigationController = UINavigationController(rootViewController: PortfoliosTableViewController())
            wireframe.show(viewController: portfoliosNavigationController)

        default:

            return wireframe.promptFor(result.description, cancelAction: "OK", actions: [])
                .map({ (_) -> AuthenticationResult in
                    result
                }).asDriver(onErrorJustReturn: result)

        }

    })

现在,问题

我的flatMapLatest期待SharedSequence<DriverSharingStrategy, AuthenticationResult>,我不会总是要回来!

在闭包内部,如果身份验证成功,我可以返回SharedSequence<DriverSharingStrategy, AuthenticationResult> ,因为我的wireframe.promptFor会返回一个observable。

但是,当身份验证失败时,我没有可观察到的返回。我的wireframe.show方法无法返回任何内容。

我该如何处理这种情况?

由于

1 个答案:

答案 0 :(得分:3)

假设切换案例.granted是认证成功,您只需返回Observable.empty()Driver.empty()

这是做什么的?

通过在flatMap操作中返回空驱动程序序列,意味着结束可观察序列。该流将接收onCompleted事件,您可以理解为流或操作成功

您可以在onCompleted方法的drive()闭包中找到以下代码。

// Your observable stream / driver sequence
.drive(onCompleted: { [unowned wireframe] in

    let portfoliosNavigationController = UINavigationController(rootViewController: PortfoliosTableViewController())

    wireframe.show(viewController: portfoliosNavigationController)

}

这应该有效。

RxCocoa Driver单位

使用Driver unit,您说您期望可观察的序列具有以下特征:

  • 无法解决
  • 观察主调度程序
  • 分享副作用(shareReplayLatestWhileConnected)

这在执行与UI相关的事情(例如您要执行的显示导航控制器的操作)时非常有用。如果是这种情况,请继续使用驱动程序。

但是如果我的流可能会遇到错误怎么办?

如果有一些机会你需要返回一个可观察的序列,以便你可以输出错误(因为你将执行一个可能出错的可观察操作,或者因为你想抛出一个错误来停止操作),然后您可以在toObservable()实例上使用Driver操作。

但要小心,因为你失去了在主线程上运行的断言(显示视图控制器所需的断言)。