Skip to content

Instantly share code, notes, and snippets.

@yutailang0119
Created July 21, 2019 17:12
Show Gist options
  • Save yutailang0119/0c15ae6a94a1153e7462e9c4716ff076 to your computer and use it in GitHub Desktop.
Save yutailang0119/0c15ae6a94a1153e7462e9c4716ff076 to your computer and use it in GitHub Desktop.
import Foundation
import Combine
protocol Request {
associatedtype Response: Decodable
var resource: Data { get }
}
struct User: Decodable {
let name: String
}
struct UserRequest: Request {
typealias Response = User
var resource: Data {
return """
{
"name": "yutailang0119"
}
""".data(using: .utf8)!
}
}
// MARK:- Use Combine.Publisher
struct RequestPublisher<R: Request>: Publisher {
typealias Output = R.Response
typealias Failure = Error
let request: R
func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input {
do {
let value = try JSONDecoder().decode(R.Response.self, from: request.resource)
subscriber.receive(value)
subscriber.receive(completion: .finished)
} catch {
subscriber.receive(completion: .failure(error))
}
}
}
do {
let submitSubject = PassthroughSubject<Void, Error>()
let responseSubject = PassthroughSubject<UserRequest.Response, Error>()
let request = UserRequest()
let publisher = submitSubject
.flatMap {
RequestPublisher(request: request)
.eraseToAnyPublisher()
}
let publisherStream = publisher
.eraseToAnyPublisher()
.subscribe(responseSubject)
let cancellable = responseSubject.sink(receiveCompletion: { conpletion in
switch conpletion {
case .finished:
print("finished")
case .failure(let error):
print("failure: \(error)")
}
}) { user in
print(user.name)
}
submitSubject.send(())
}
// MARK:- Use Combine.Future
struct RequestFuture<R: Request> {
let request: R
func makeFuture() -> Future<R.Response, Error> {
return Future { promise in
do {
let value = try JSONDecoder().decode(R.Response.self, from: self.request.resource)
promise(.success(value))
} catch {
promise(.failure(error))
}
}
}
}
do {
let submitSubject = PassthroughSubject<UserRequest, Error>()
let responseSubject = PassthroughSubject<UserRequest.Response, Error>()
let request = UserRequest()
let future = submitSubject
.map(RequestFuture.init(request:))
.map { $0.makeFuture() }
.flatMap { $0.eraseToAnyPublisher() }
let futureStream = future
.eraseToAnyPublisher()
.subscribe(responseSubject)
let cancellable = responseSubject.sink(receiveCompletion: { conpletion in
switch conpletion {
case .finished:
print("finished")
case .failure(let error):
print("failure: \(error)")
}
}) { user in
print(user.name)
}
submitSubject.send(request)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment