Вы можете использовать Future
для подключения обратного вызова responseObject
к комбайну Publisher
. У меня нет Alamofire для тестирования, но я думаю, что должно работать следующее:
func doRequest<T: Mappable>(request: URLRequestConvertible) -> AnyPublisher<T, AFError> {
return Future { promise in
self.session
.request(request)
.validate()
.responseObject { (response: AFDataResponse<T>) in
promise(response.result)
}
}.eraseToAnyPublisher()
}
Обратите внимание, что это несколько проще, чем версия RxSwift, потому что promise
принимает Result
напрямую, поэтому мы не нужно переключаться response.result
.
A Future
является своего рода «теплым» издателем. Это похоже на горячую наблюдаемость, потому что он выполняет свое тело немедленно и только один раз, поэтому он немедленно запускает запрос Alamofire. Это также похоже на наблюдаемую холодность, потому что каждый подписчик в конечном итоге получает значение или ошибку (при условии, что вы в конечном итоге вызовете promise
). Future
выполняет свое тело только один раз, но кэширует Result
, который вы передаете promise
.
Вы можете создать действительно холодного издателя, заключив Future
в Deferred
:
func doRequest<T: Mappable>(request: URLRequestConvertible) -> AnyPublisher<T, AFError> {
return Deferred {
Future { promise in
self.session
.request(request)
.validate()
.responseObject { (response: AFDataResponse<T>) in
promise(response.result) }
}
}.eraseToAnyPublisher()
}
Deferred
вызывает его тело для создания нового внутреннего Publisher
каждый раз, когда вы подписываетесь на него. Поэтому каждый раз, когда вы подписываетесь, вы создаете новый Future
, который немедленно запускает новый запрос Alamofire. Это полезно, если вы хотите использовать оператор retry
, как в этот вопрос .