[英]RxSwift: tap a button to do a request with Alamofire, how to make it work?
I have some UI rx button tap, I want to connect it to the network rx part.我有一些 UI rx 按钮点击,我想将它连接到网络 rx 部分。
Here is Rx btn tap part:这是 Rx btn 抽头部分:
btn.rx.tap.take(1).flatMap { [unowned self] () -> Observable<Bool> in
// ...
return NetManager.standard.request()
}.debug().do(onNext: { _ in
print("The data flows here")
}).flatMapLatest { (echo: Bool) -> Observable<Bool> in
if echo{
if let app = UIApplication.shared.delegate as? AppDelegate{
app.goHome()
}
return Observable.of(true)
}
else{
return Observable.of(false)
}
}.subscribe(onNext: { (result) in
// ... , do sth with result
}).disposed(by: rx.disposeBag)
Here is net request part with Alamofire:这是 Alamofire 的网络请求部分:
class NetManager: NSObject {
static let standard = NetManager()
var dataRequest: DataRequest?
func request() -> Observable<Bool> {
return Observable<Bool>.create{ (observer) -> Disposable in
let data = // ...
// ...
self.dataRequest = AF.request(aURL, method: HTTPMethod.post, parameters: data, encoder: JSONParameterEncoder.prettyPrinted, headers: aHead).response { (response: DataResponse<Data?>) in
self.hud?.hide()
if let data = response.data{
observer.onNext(true)
// ....
}
else{
observer.onNext(false)
}
}
observer.onCompleted()
return Disposables.create{}
}
}
}
Here is the debug info:这是调试信息:
Controller.swift:141 (viewDidLoad()) -> subscribed
Controller.swift:141 (viewDidLoad()) -> 订阅
Controller.swift:141 (viewDidLoad()) -> Event completed
Controller.swift:141 (viewDidLoad()) -> 事件完成
Controller.swift:141 (viewDidLoad()) -> isDisposed
Controller.swift:141 (viewDidLoad()) -> isDisposed
The result is, the do( next )
part seems like that it has not been called.结果是,
do( next )
部分似乎没有被调用。 Because no print
in console.因为控制台中没有
print
。
The question is, how to make the rx logic work?问题是,如何使 rx 逻辑工作?
Here is what I tried:这是我尝试过的:
turn btn.rx.tap.flatMap
to btn.rx.tap.take(1).flatMap
将
btn.rx.tap.flatMap
转为btn.rx.tap.take(1).flatMap
because from this issue因为从这个问题
if a flatMap completion would terminate the outer stream, it would mean that no more button taps would be registered in your stream, which don't really make sense.
如果 flatMap 完成将终止外部 stream,则意味着您的 stream 中将不再注册按钮点击,这实际上没有意义。
Seen from this question从这个问题看
btn.rx.tap.map { () -> Observable<Bool> in
return NetManager.standard.request()
}.flatMapLatest { (observer: Observable<Bool>) -> Observable<Bool> in
// of cource, I can subscribe to observer
/*
observer.subscribe(onNext: { (echo) in
})
*/
// how to get the event element elegantly.
return Observable.of(false)
}.subscribe(onNext: { (_) in
}).disposed(by: rx.disposeBag)
how to do this more elegantly.如何更优雅地做到这一点。
The main issue here is that when performing the network request, you are not waiting for the network call to respond.这里的主要问题是在执行网络请求时,您并没有等待网络调用响应。 So
observer.onComplete()
is triggered before observer.onNext()
所以
observer.onComplete()
在observer.onNext()
之前触发
class NetManager: NSObject {
static let standard = NetManager()
var dataRequest: DataRequest?
func request() -> Observable<Bool> {
return Observable<Bool>.create { (observer) -> Disposable in
let data = // ...
// ...
self.dataRequest = AF.request(aURL, method: HTTPMethod.post, parameters: data, encoder: JSONParameterEncoder.prettyPrinted, headers: aHead).response { (response: DataResponse<Data?>) in
self.hud?.hide()
if let data = response.data {
observer.onNext(true)
// ...
}
else {
observer.onNext(false)
}
observer.onComplete() // Moving it here instead will wait for the response
}
return Disposables.create { }
}
}
}
At this point, your code should work as it is, but you're still overcomplicating a very simple thing.此时,您的代码应该可以正常工作,但是您仍然使一个非常简单的事情过于复杂。
Here is what to do:这是做什么:
btn.rx.tap
.flatMap { _ in
return NetManager.standard.request()
}
.subscribe(onNext: { (success) in
if success {
if let app = UIApplication.shared.delegate as? AppDelegate {
app.goHome()
}
}
})
.disposed(by: rx.disposeBag)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.