RxSwift回调在结果之前首先返回

时间:2017-02-12 10:49:01

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

我正在使用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

}

2 个答案:

答案 0 :(得分:1)

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

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

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

为了更好地了解正在发生的事情,我建议在使用Observable的部分周围添加.debug()语句,这样可以让您准确了解发生的事件,并帮助您准确理解错误的原因:)

答案 1 :(得分:0)

前段时间我遇到了同样的问题,如果出现错误,我想在Alert中显示onError,但不会丢弃可观察的内容。

我通过捕获错误并使用案例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)