flatMap 不会被调用
flatMap doesn't get invoked
我正在尝试使用两个单独的函数调用来验证用户的电子邮件和密码。
两个函数 return AnyPublisher 发布者,我使用 combineLatest 将 returned 值(每个验证调用 returns 它正在验证的字符串)收集到一个元组中。
然后我使用 flatMap 发出网络请求以使用由 combineLatest 编辑的值 return 注册用户,但是 flatMap 运算符永远不会被调用。
validator.validate(text: email, with: [.validEmail])
.combineLatest(validator.validate(text: password, with: [.notEmpty]))
.flatMap { credentials in
return self.userSessionRepository.signUp(email: credentials.0, password: credentials.1)
}
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print(error)
self.indicateErrorSigningIn(error)
case .finished:
self.goToSignInNavigator.navigateToOtp()
}
}, receiveValue: { _ in })
.store(in: &subscriptions)
signUp(email:password:) returns AnyPublisher
验证器函数如下:
public func validate(text: String, with rules: [Rule]) -> AnyPublisher<String, ErrorMessage> {
rules.publisher
.compactMap { [=11=].check(text) }
.setFailureType(to: ErrorMessage.self)
.flatMap {
Fail<Void, ErrorMessage>(error: ErrorMessage(title: "Error", message: [=11=].description))
}
.map { text }
.eraseToAnyPublisher()
}
注册函数:
public func signUp(email: String, password: String) -> AnyPublisher<Void, ErrorMessage> {
remoteAPI.signUp(email: email, password: password)
.flatMap(dataStore.save)
.mapError { error -> ErrorMessage in
return ErrorMessage(title: "Error", message: error.description)
}
.eraseToAnyPublisher()
}
它调用了这两个函数:
public func signUp(email: String, password: String) -> AnyPublisher<Confirmation, RemoteError> {
guard email == "john.doe@email.com" else {
return Fail<Confirmation, RemoteError>(error: .invalidCredentials)
.eraseToAnyPublisher()
}
return Just(Confirmation(otp: "", nonce: "abcd"))
.setFailureType(to: RemoteError.self)
.eraseToAnyPublisher()
}
public func save(confirmation: Confirmation) -> AnyPublisher<Void, RemoteError> {
self.nonce = confirmation.nonce
return Empty().eraseToAnyPublisher()
}
我不确定哪里出了问题,但可能是我对 Combine 了解不够,因为我最近才开始学习它。
我想出来了
问题出在 validate(text:with:) 函数上。
如果出现错误,该函数会正常运行,但如果没有错误,该函数不会发出任何值,这就是 flatMap 或管道中的任何其他运算符未被调用的原因。
它没有发出任何值的原因归结为在 compactMap 中调用的 check(_:) 函数的工作方式。它 returns 一个可选的字符串,它是一个错误信息。但如果没有错误,则没有字符串,因此不会发出任何值。
因此,不会评估对 .map { text } 的调用,也不会返回凭据。
我已将代码更改为此,现在程序运行正常:
public func validate(text: String, with rules: [Rule]) -> AnyPublisher<String, ErrorMessage> {
rules.publisher
.setFailureType(to: ErrorMessage.self)
.tryMap { rule -> String in
if let error = rule.check(text) {
throw ErrorMessage(title: "Error", message: error)
}
return text
}
.mapError { error -> ErrorMessage in
return error as! ErrorMessage
}
.eraseToAnyPublisher()
}
我正在尝试使用两个单独的函数调用来验证用户的电子邮件和密码。
两个函数 return AnyPublisher 发布者,我使用 combineLatest 将 returned 值(每个验证调用 returns 它正在验证的字符串)收集到一个元组中。
然后我使用 flatMap 发出网络请求以使用由 combineLatest 编辑的值 return 注册用户,但是 flatMap 运算符永远不会被调用。
validator.validate(text: email, with: [.validEmail])
.combineLatest(validator.validate(text: password, with: [.notEmpty]))
.flatMap { credentials in
return self.userSessionRepository.signUp(email: credentials.0, password: credentials.1)
}
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print(error)
self.indicateErrorSigningIn(error)
case .finished:
self.goToSignInNavigator.navigateToOtp()
}
}, receiveValue: { _ in })
.store(in: &subscriptions)
signUp(email:password:) returns AnyPublisher
验证器函数如下:
public func validate(text: String, with rules: [Rule]) -> AnyPublisher<String, ErrorMessage> {
rules.publisher
.compactMap { [=11=].check(text) }
.setFailureType(to: ErrorMessage.self)
.flatMap {
Fail<Void, ErrorMessage>(error: ErrorMessage(title: "Error", message: [=11=].description))
}
.map { text }
.eraseToAnyPublisher()
}
注册函数:
public func signUp(email: String, password: String) -> AnyPublisher<Void, ErrorMessage> {
remoteAPI.signUp(email: email, password: password)
.flatMap(dataStore.save)
.mapError { error -> ErrorMessage in
return ErrorMessage(title: "Error", message: error.description)
}
.eraseToAnyPublisher()
}
它调用了这两个函数:
public func signUp(email: String, password: String) -> AnyPublisher<Confirmation, RemoteError> {
guard email == "john.doe@email.com" else {
return Fail<Confirmation, RemoteError>(error: .invalidCredentials)
.eraseToAnyPublisher()
}
return Just(Confirmation(otp: "", nonce: "abcd"))
.setFailureType(to: RemoteError.self)
.eraseToAnyPublisher()
}
public func save(confirmation: Confirmation) -> AnyPublisher<Void, RemoteError> {
self.nonce = confirmation.nonce
return Empty().eraseToAnyPublisher()
}
我不确定哪里出了问题,但可能是我对 Combine 了解不够,因为我最近才开始学习它。
我想出来了
问题出在 validate(text:with:) 函数上。
如果出现错误,该函数会正常运行,但如果没有错误,该函数不会发出任何值,这就是 flatMap 或管道中的任何其他运算符未被调用的原因。
它没有发出任何值的原因归结为在 compactMap 中调用的 check(_:) 函数的工作方式。它 returns 一个可选的字符串,它是一个错误信息。但如果没有错误,则没有字符串,因此不会发出任何值。
因此,不会评估对 .map { text } 的调用,也不会返回凭据。
我已将代码更改为此,现在程序运行正常:
public func validate(text: String, with rules: [Rule]) -> AnyPublisher<String, ErrorMessage> {
rules.publisher
.setFailureType(to: ErrorMessage.self)
.tryMap { rule -> String in
if let error = rule.check(text) {
throw ErrorMessage(title: "Error", message: error)
}
return text
}
.mapError { error -> ErrorMessage in
return error as! ErrorMessage
}
.eraseToAnyPublisher()
}