Rxswift 在发送 api 请求之前验证输入
Rxswift validate inputs before sending api request
我有一个登录屏幕,我通过组合 email/password Bool Observable 显示之前在文本字段和禁用按钮上方的错误输入,但是现在设计已更改,我想检查 email/password 是否是在发送请求或显示警报对话框之前不为空
我的问题是如何在点击请求之前验证输入是否有效:
登录视图模型:
var emailValid: Observable<Bool> {
return emailSubject.asObservable().map { [=11=].count > 0 && [=11=].isEmail}
}
signInDidTapSubject
.withLatestFrom(credentialsObservable)
.flatMapLatest { credentials -> Observable<Event<Result<UserResponse>>> in
self.loadInProgress.accept(true)
return network.login(with: credentials).materialize()
}
.subscribe(onNext: { [weak self] event in
self?.loadInProgress.accept(false)
switch event {
case .next(let result):
switch result{
case .Success(let user):
self?.loginResultSubject.onNext(user)
case .Failure(let error):
self?.errorsSubject.onNext(error)
}
case .error( _):
print("error")
default:
break
}
})
.disposed(by: disposeBag)
VC:
loginButton.rx.tap.asObservable()
.debounce(0.5, scheduler: MainScheduler.instance)
.subscribe(viewModel.input.loginButtonTapped).disposed(by: disposeBag)
解决这个问题的方法是问问自己,"What inputs do I need to produce this output?"
这里有两个输出 "User" 和 "Error"。让我们先做快乐的道路。你需要什么输入来产生一个用户?只是一个成功的网络响应。但是你需要什么输入来产生网络响应?好吧,您需要电子邮件和密码,但触发事件是点击登录按钮,如果数据无效,则不应发出请求:
let networkResponse = loginTrigger
.withLatestFrom(credentials)
.filter { [=10=].email.isEmail && ![=10=].password.isEmpty }
.flatMapLatest {
network.login(with: [=10=])
.materialize()
}
.share(replay: 1)
let user = networkResponse
.filter { [=10=].element != nil }
.map { [=10=].element! }
现在,您需要什么输入来生成错误输出?如果有,您需要网络请求中的错误,并且您需要知道电子邮件或密码是否无效。但是,如果点击登录按钮,您只想知道无效输入...
很多,但它是这样分解的:
let networkError = networkResponse
.filter { [=11=].error != nil }
.map { [=11=].error! }
let invalidEmailError = loginTrigger
.withLatestFrom(email)
.filter { ![=11=].isEmail }
.map { _ in UIError.badEmail as Error }
let invalidPasswordError = loginTrigger
.withLatestFrom(password)
.filter { [=11=].isEmpty }
.map { _ in UIError.badPassword as Error }
let error = Observable.merge(networkError, invalidEmailError, invalidPasswordError)
看看效果如何?依次获取每个输出并找出使该输出工作所需的输入。
我有一个登录屏幕,我通过组合 email/password Bool Observable 显示之前在文本字段和禁用按钮上方的错误输入,但是现在设计已更改,我想检查 email/password 是否是在发送请求或显示警报对话框之前不为空
我的问题是如何在点击请求之前验证输入是否有效:
登录视图模型:
var emailValid: Observable<Bool> {
return emailSubject.asObservable().map { [=11=].count > 0 && [=11=].isEmail}
}
signInDidTapSubject
.withLatestFrom(credentialsObservable)
.flatMapLatest { credentials -> Observable<Event<Result<UserResponse>>> in
self.loadInProgress.accept(true)
return network.login(with: credentials).materialize()
}
.subscribe(onNext: { [weak self] event in
self?.loadInProgress.accept(false)
switch event {
case .next(let result):
switch result{
case .Success(let user):
self?.loginResultSubject.onNext(user)
case .Failure(let error):
self?.errorsSubject.onNext(error)
}
case .error( _):
print("error")
default:
break
}
})
.disposed(by: disposeBag)
VC:
loginButton.rx.tap.asObservable()
.debounce(0.5, scheduler: MainScheduler.instance)
.subscribe(viewModel.input.loginButtonTapped).disposed(by: disposeBag)
解决这个问题的方法是问问自己,"What inputs do I need to produce this output?"
这里有两个输出 "User" 和 "Error"。让我们先做快乐的道路。你需要什么输入来产生一个用户?只是一个成功的网络响应。但是你需要什么输入来产生网络响应?好吧,您需要电子邮件和密码,但触发事件是点击登录按钮,如果数据无效,则不应发出请求:
let networkResponse = loginTrigger
.withLatestFrom(credentials)
.filter { [=10=].email.isEmail && ![=10=].password.isEmpty }
.flatMapLatest {
network.login(with: [=10=])
.materialize()
}
.share(replay: 1)
let user = networkResponse
.filter { [=10=].element != nil }
.map { [=10=].element! }
现在,您需要什么输入来生成错误输出?如果有,您需要网络请求中的错误,并且您需要知道电子邮件或密码是否无效。但是,如果点击登录按钮,您只想知道无效输入...
很多,但它是这样分解的:
let networkError = networkResponse
.filter { [=11=].error != nil }
.map { [=11=].error! }
let invalidEmailError = loginTrigger
.withLatestFrom(email)
.filter { ![=11=].isEmail }
.map { _ in UIError.badEmail as Error }
let invalidPasswordError = loginTrigger
.withLatestFrom(password)
.filter { [=11=].isEmpty }
.map { _ in UIError.badPassword as Error }
let error = Observable.merge(networkError, invalidEmailError, invalidPasswordError)
看看效果如何?依次获取每个输出并找出使该输出工作所需的输入。