【问题标题】:RxSwift callback return first before resultRxSwift 回调在结果之前先返回
【发布时间】:2017-02-12 10:49:01
【问题描述】:

我正在使用 Firebase FirAuth API,在 API 返回结果之前,Disposables.create() 已返回并且不再可点击(我知道这可能是由于调用 API 后没有 observer.onCompleted 造成的。有没有办法等待它/听听结果?

public func login(_ email: String, _ password: String) -> Observable<APIResponseResult> {

    let observable = Observable<APIResponseResult>.create { observer -> Disposable in

        let completion : (FIRUser?, Error?) -> Void =  {  (user, error) in

            if let error = error {
                UserSession.default.clearSession()
                observer.onError(APIResponseResult.Failure(error))
                observer.on(.completed)
                return
            }

            UserSession.default.user.value = user!
            observer.onNext(APIResponseResult.Success)
            observer.on(.completed)
            return
        }

        DispatchQueue.main.async {
            FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: completion)
        }

        return Disposables.create()
    }

    return observable

}

【问题讨论】:

  • Firebase 是异步的,并非旨在以同步方式返回数据。虽然你可以强制这种模式,但它会导致很多长期问题。所有的 DispatchQueue 和回调都应该被移除,否则将是一场噩梦。让 Firebase 完成它的工作;一旦数据在 Firebase 闭包中可用,然后继续进行 UI 中的下一步,处理该数据等。代码可能过于复杂 - 也许如果你能解释你想要完成的事情,一个明确的解决方案可能是提供而不是解决方法。
  • 感谢您的解释。我想要实现的是向视图控制器返回正确的响应,以便我重定向(如果成功)或发出警报(如果错误)。在这种情况下,我总是得到一个空错误,因为它总是首先返回错误场景
  • 只需改变流程:捕获用户信息,然后通过Firebase调用创建用户。在闭包内,您将遇到错误(检查原因的错误代码)并告诉用户错误没有错误,以便您可以继续显示下一个 viewController 或下一步是什么.应该是大约 6 行代码,并且可以在没有调度队列和回调的情况下完成。

标签: ios swift firebase firebase-authentication rx-swift


【解决方案1】:

您的假设是正确的,即 onError / onCompletion 事件会终止 Observable 序列。意思是,在任何情况下,序列都不会再发出任何事件。

作为旁注,您不需要在 .onError() 之后执行 .on(.completed) ,因为 onError 已经终止了序列。

您编写return Disposables.create() 的部分返回一个 Disposable 对象,以便稍后可以将 observable 添加到 DisposeBag 中,该 DisposeBag 将在 DisposeBag 被释放时处理释放 observable,因此它应该立即返回,但它不会终止您的请求。

为了更好地了解正在发生的事情,我建议在使用 Observable 的部分周围添加 .debug() 语句,这将使您能够准确了解正在发生的事件并帮助您准确了解问题所在:)

【讨论】:

  • 感谢您指出这一点。我想了解 RxSwift 如何与 Firebase API 一起工作,因此我正在尝试调用并等待响应。
【解决方案2】:

我前段时间遇到过同样的问题,如果出现错误,我想在 onError 中显示 Alert,但不处理 observable。

我通过捕获错误并返回enum 以及.success(MyType).error(Error) 的情况解决了这个问题

一个例子:

// ApiResponseResult.swift
enum ApiResponseResult {
    case error(Error) 
    case success(FIRUser)  
}

// ViewModel
func login(...) -> Observable<ApiResponseResult> {
    let observable = Observable.create { ... }
    return observable.catchError { error in
        return Observable<ApiResponseResult>.just(.error(error))
    }
}

// ViewController
viewModel
    .login
    .subscribe(onNext: { result in 
        switch result {
        case .error(let error):
            // Alert or whatever
            break
        case .success(let user):
            // Hurray
            break
        } 
    })
    .addDisposableTo(disposeBag)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 2019-05-13
    • 2021-09-06
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多