在 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()
}
下面是三个函数。第一个是我需要重构的函数。基本上我希望的是使用 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()
}