开关映射的 RxSwift 等效项

Posted

技术标签:

【中文标题】开关映射的 RxSwift 等效项【英文标题】:RxSwift equivalent for switchmap 【发布时间】:2019-11-19 17:59:50 【问题描述】:

在 RxJS 中,您可以将 observable 中的值用于新的 observable。例如:

this.authService.login(username, password).pipe(
  switchMap((success: boolean) => 
    if(success) 
      return this.contactService.getLoggedInContact()
     else 
      return of(null)
    
  )
).subscribe(contact => 
  this.contact = contact
)

但现在我必须用 Swift 做一个项目,我想实现同样的目标。我可以让这两种方法工作,但是将第一个可观察的结果用于第二个可观察的结果是我无法工作的。 switchMap 管道是 RxSwift 中不存在的东西,我找不到等价物。

我尝试将登录函数的结果映射到可观察对象,然后对其进行平面映射,但不幸的是,这不起作用。

在 Swift 中不使用订阅的最佳方法是什么?

编辑我尝试过平面地图:

APIService.login(email: "username", password: "password")
  .flatMapLatest  result -> Observable<Contact> in
    if result 
      return APIService.getLoggedInContact()
     else 
      return .of()
    
  .subscribe(onNext: result in
    print("Logged in contact: \(result)")
  , onError: Error in
    print(Error)
  ).disposed(by: disposeBag)

但不幸的是,这不起作用,我收到错误Thread 1: EXC_BAD_ACCESS (code=1, address=0x13eff328c)

EDIT2:

这是登录功能

static func login(email: String, password: String) -> Observable<Bool> 
        return Observable<String>.create  (observer) -> Disposable in
            Alamofire.request(self.APIBASEURL + "/contact/login", method: .post, parameters: [
                "email": email,
                "password": password
            ], encoding: JSONEncoding.default).validate().responseJSON(completionHandler: response in
                if (response.result.isSuccess) 
                    guard let jsonData = response.data else 

                        return observer.onError(CustomError.api)
                    
                    let decoder = JSONDecoder()

                    let apiResult = try? decoder.decode(ApiLogin.self, from: jsonData)
                    return observer.onNext(apiResult!.jwt)
                 else 
                    return self.returnError(response: response, observer: observer)
                
            )

            return Disposables.create()
        .maptoken in
            return KeychainWrapper.standard.set(token, forKey: "authToken")
        
    

这是 getLoggedInContact 函数

static func getLoggedInContact() -> Observable<Contact> 
        return Observable.create  observer -> Disposable in
            Alamofire.request(self.APIBASEURL + "/contact/me", method: .get, headers: self.getAuthHeader())
              .validate().responseJSON(completionHandler: response in
                if (response.result.isSuccess) 
                    guard let jsonData = response.data else 

                        return observer.onError(CustomError.api)
                    

                    let decoder = JSONDecoder()
                    decoder.dateDecodingStrategy = .formatted(.apiNewsDateResult)

                    let apiResult = try? decoder.decode(Contact.self, from: jsonData)
                    return observer.onNext(apiResult!)
                 else 
                    return self.returnError(response: response, observer: observer)
                
            )

            return Disposables.create()
        
    

【问题讨论】:

尝试清理和重建。您在编辑中所做的应该可以工作......顺便说一句,使用.empty() 而不是.of() 会更惯用。 @DanielT。清理和重建不起作用:/它在 FlatMapLatest 类的 run 方法中崩溃,并出现相同的错误。 您的get... 函数中或代码中的其他地方一定有什么事情发生了。我将代码复制粘贴到一个沙盒项目中,它运行良好。 @DanielT。嗯,好的,谢谢!我会调查一下,我只是想象它不会是那些函数,因为作为独立函数,它们按预期工作。 @DanielT。经过大量测试,我找不到问题所在。我添加了功能,你有什么不寻常的地方吗? 【参考方案1】:

flatMapLatest 的操作符与 RxJS 中的 switchMap 完全相同。

你可以找到usage example here

【讨论】:

谢谢,我刚试过这个,但不幸的是它在到达 flatMap 时崩溃了。即使我在 if 语句之前打印。 ://

以上是关于开关映射的 RxSwift 等效项的主要内容,如果未能解决你的问题,请参考以下文章

开关数组中的 Rxswift Async api

RxSwift 映射问题

RxSwift:将可完成映射到单个可观察?

RxSwift:结合不同类型的可观察对象和映射结果

RxSwift - Observable.generate - 使用附加映射处理顺序请求

tableView.rx.itemSelected 中的 RxSwift 双映射