【问题标题】:RxSwift equivalent for switchmap开关映射的 RxSwift 等效项
【发布时间】: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()
        }.map{token 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。经过大量测试,我找不到问题所在。我添加了功能,你有什么不寻常的地方吗?

标签: swift rxjs reactive-programming rx-swift reactivex


【解决方案1】:

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

你可以找到usage example here

【讨论】:

  • 谢谢,我刚试过这个,但不幸的是它在到达 flatMap 时崩溃了。即使我在 if 语句之前打印。 ://
猜你喜欢
  • 2014-06-11
  • 1970-01-01
  • 1970-01-01
  • 2021-08-12
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多