[英]How to transform rx_tap of UIButton to a network request directly without sending the request in a nested subscribe?
假設我有一個UIButton loginButton
,我想在使用以下代碼點擊按鈕時發送一個網絡請求:
override func viewDidLoad() {
super.viewDidLoad()
let session = self.session // NSURLSession
loginButton.rx_tap.subscribeNext { [unowned self] in
session.rx_response(myRequest).subscribe { event in
switch event {
case .Next(let data, let response):
// Handling Response
case .Error(let error):
// Handling Error
default:
return
}
}.addDisposableTo(disposeBag)
}.addDisposableTo(disposeBag)
}
在這種情況下,即使網絡請求發生錯誤,我也可以通過點擊按鈕重新發送請求。
雖然代碼效果很好,但是由於嵌套訂閱,我認為它有點難看。 我嘗試了flatMap
方法來展平訂閱:
loginButton.rx_tap
.flatMap {
return session.rx_response(myRequest)
}
.subscribe { event in
switch event {
case .Next(let data, let response):
print("Next")
case .Error(let error):
print(error)
default:
return
}
}
.addDisposableTo(disposeBag)
上面的兩個代碼片段似乎具有不同的邏輯。 后一種訂閱僅在正常訂閱沒有出錯的情況下起作用,而不是在每次點擊按鈕時訂閱網絡請求。
有什么辦法可以壓平正式片段嗎?
添加了嵌套訂閱的代碼段:
loginButton.rx_tap
.debug("LoginButtonTapped")
.subscribeNext {
let disposable = session.rx_response(myRequest)
.debug("AuthorizationRequest")
.subscribe(
onNext: { [unowned self] data, response in
// Handling Response
},
onError: { [unowned self] error in
// Showing Error
})
disposable.addDisposableTo(self.disposeBag)
let alert = UIAlertController(title: "Please Wait.", message: "Requesting Tokens", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel) { _ in
disposable.dispose()
alert.dismissViewControllerAnimated(true, completion: nil)
})
self.presentViewController(alert, animated: true, completion: nil)
}.addDisposableTo(disposeBag)
使用以下代碼可以捕獲錯誤:
let disposable = loginButton.rx_tap
.map { session.rx_response(request) }
.flatMap { [unowned self] in $0.catchError(self.presentError) }
.subscribeNext { data, response in
// Handling Response
}
如果需要,我還需要取消網絡請求。 如果我在上述摘要中手動處理disposable
,則訂閱將被處理,我無法再次發送請求。
您有2種方法來實現要求的行為。 第一個是用戶map
,然后switchLatest
到switchLatest
,這是經典方法。 第二個是如果您需要按網絡請求順序進行catch
/ retry
,請使用flatMap
用戶。
Ash Furrow在研討會演示代碼中使用第二個示例和Moya給出了一個非常不錯的示例:
submitButton.rx_tap.map { _ -> Observable<MoyaResponse> in
return provider.request(.Image)
}.flatMap() { obs in
return obs.filterSuccessfulStatusCodes()
.mapImage()
.catchError(self.presentError)
.filter({ (thing) -> Bool in
return thing != nil
})
}
.take(1)
.bindTo(imageView.rx_image)
.addDisposableTo(disposeBag)
另外,您可以檢查RxSwift存儲庫中的Github示例,以了解如何處理這些事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.