RxSwift中如何链式调用login与getUser请求实现全链路同步完成
问题核心
现有代码的问题是getUser()是独立于登录请求的Rx序列之外的异步逻辑,do(onSuccess:)不会等待内部异步任务完成,就会直接执行后续的asVoid返回结果,导致用户信息还没处理完就已经触发了跳转逻辑。
改造方案
第一步 调整getUser方法返回值
把原来无返回值的getUser改成返回Single<Void>,将用户请求、存储逻辑整合成完整的可串联序列:
private func getUser() -> Single<Void> { return request(type: UserNew.self, endpoint: ApiUserRouter.me) .do(onSuccess: { [unowned self] user in // 同步存储用户信息到数据库和全局管理类 try self.realmManager.writeSync({ realm in realm.add(user, update: .modified) }) self.apiService.authenticationManager.setUser(user: user) }) .asVoid() }
第二步 用flatMap串联全流程
修改login方法,使用flatMap操作符将令牌存储后的逻辑切换到用户信息请求流,只有当用户信息处理完成后,整个序列才会结束:
func login(email: String, password: String) -> Single<Void> { return request(type: Auth.self, endpoint: ApiAuthRouter.login(email: email, password: password)) // 第一步:登录成功后存储令牌 .do(onSuccess: { [unowned self] auth in self.apiService.authenticationManager.setAuthTokens(auth: auth) }) // 第二步:令牌存储完成后,串联用户信息请求流 .flatMap { [unowned self] _ in self.getUser() } }
外部调用示例
在订阅login方法的成功回调后再执行首页跳转,就能保证所有逻辑都执行完成:
login(email: "用户输入的邮箱", password: "用户输入的密码") .subscribe(onSuccess: { _ in // 登录、存令牌、拉取用户信息、存用户信息全流程完成,跳转首页 Router.navigateToHome() }, onError: { error in // 统一处理全流程任意环节的错误,比如登录失败、用户信息拉取失败 Toast.showError(message: error.localizedDescription) }) .disposed(by: disposeBag)
方案优势
- 所有流程严格按顺序执行,前一步失败就会终止后续逻辑,不会出现状态不一致的问题
- 全链路错误可以在同一个订阅里统一处理,不需要分散管理多个异步流的异常
- 完全依赖Rx原生操作符保证时序,没有额外的状态标记逻辑,代码可读性和可维护性更高
内容的提问来源于stack exchange,提问作者Dick Thunder
相关产品推荐
相关产品推荐

