简体   繁体   English

RxSwift:点击一个按钮用 Alamofire 发出请求,如何使它工作?

[英]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).flatMapbtn.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM