在 Swift 中使用 Future 时链接调用类似于 PromiseKit

Chaining calls when using Future in Swift similar to PromiseKit

下面是三个函数。第一个是我需要重构的函数。基本上我希望的是使用 Promise Kit 可以实现的类似的东西,但在这种情况下使用 Swifts 组合框架。

第二个函数loginWithFacebook()return是AuthCredential。 此 AuthCredential 需要传递给最后一个函数,该函数 return 是一个类型 Future<UserProfileCompact, Error>,与主函数(第一个函数)类似 return 类型。

我的问题是有没有办法以 Swifty 的方式实现这个,类似于 Promise Kit 做这个操作: return loginWithFacebook().then {loginWithFirebase(:_)}

    // Call site is a View Model 
    // Main Function that needs to be refactored
    func loginwithFacebook() -> Future<UserProfileCompact, Error> {
        //This returs a Future Firebase Credential
        loginWithFacebook()
        //The above credential needs to be passed to this method and this returns a type Future<UserProfileCompact, Error> 
        loginWithFirebase(<#T##credentials: AuthCredential##AuthCredential#>)
    }
    
    private func loginWithFacebook() -> Future<AuthCredential,Error> {
        return Future { [weak self] promise in
            self?.loginManager.logIn(permissions: ["public_profile","email"], from: UIViewController()) { (loginResult, error) in
                if let error = error {
                    promise(.failure(error))
                } else if loginResult?.isCancelled ?? false {
                    //fatalError()
                }
                else if let authToken = loginResult?.token?.tokenString {
                    let credentials = FacebookAuthProvider.credential(withAccessToken: authToken)
                    
                    promise(.success(credentials))
                }
                else{
                    fatalError()
                }
            }
        }
    }
    
    private func loginWithFirebase(_ credentials: AuthCredential) -> Future<UserProfileCompact, Error> {
        return Future { promise in
            Auth.auth().signIn(with: credentials) { (result, error) in
                if let error = error {
                    //Crashlytics.crashlytics().record(error: error)
                    promise(.failure(error))
                }
                else if let user = result?.user {
                    //Crashlytics.crashlytics().setUserID(user.uid)
                    let profile = UserProfileCompactMapper.map(firebaseUser: user)
                    promise(.success(profile))
                }
                else {
                    fatalError()
                }
            }
        }
    }

您可以使用 .flatMap 运算符,它从上游获取值并生成发布者。这看起来像下面这样。

请注意,最好在函数边界 return 类型擦除 AnyPublisher,而不是函数内部使用的特定发布者

func loginwithFacebook() -> AnyPublisher<UserProfileCompact, Error> {
   loginWithFacebook().flatMap { authCredential in
      loginWithFirebase(authCredential)
   }
   .eraseToAnyPublisher()
}