如何在 RxSwift 中 return 与 flatMapLatest 不同的类型?

How to return different types from flatMapLatest in RxSwift?

我正在关注 RxSwift 示例 GitHub SignUp using Driver,并以类似的方式结束。

我有一个执行身份验证的网络请求,并且 return 是一个 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> 而我并不总是 return!

在闭包内部,我可以 return SharedSequence<DriverSharingStrategy, AuthenticationResult> 如果身份验证成功 ,因为我的 wireframe.promptFor return 是一个可观察对象.

但是,当身份验证失败 时,我没有return 的可观察对象。我的 wireframe.show 方法没有 return 任何东西。

我该如何处理这种情况?

谢谢

假设 switch case .granted 是认证成功,你可以简单地 return Observable.empty()Driver.empty().

那有什么作用?

通过在 flatMap 操作中 return 一个空的驱动程序序列,您的意思是结束可观察序列。流将收到 onCompleted 事件,您可以将其理解为 流或操作成功

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

// 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 相关的事情时通常很有用(比如你想做的是显示导航控制器)。如果是这种情况,请继续使用驱动程序。

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

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

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