Skip to content

Instantly share code, notes, and snippets.

@AquaGeek
Created August 19, 2020 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AquaGeek/0bdeec31263b4a871d5f02426719fe0a to your computer and use it in GitHub Desktop.
Save AquaGeek/0bdeec31263b4a871d5f02426719fe0a to your computer and use it in GitHub Desktop.
Example of how to use SignalProducer to fetch multiple pages
private func fetchAllUsers() -> SignalProducer<[User], Error> {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
func fetchUsers(since lastSeenUserID: Int?) -> SignalProducer<[User], Error> {
var components = URLComponents(string: "https://api.github.com/users")!
if let userID = lastSeenUserID {
components.queryItems = [
URLQueryItem(name: "since", value: userID.description)
]
}
var request = URLRequest(url: components.url!)
request.setValue("application/vnd.github.v3+json", forHTTPHeaderField: "Accept")
return URLSession.shared.reactive
.data(with: request)
.flatMap(.concat) { (data, _) -> SignalProducer<[User], Error> in
SignalProducer { () in
Result<[User], Error> {
try decoder.decode([User].self, from: data)
}
}
}
}
// Adapted from the `repeat` operator: https://github.com/ReactiveCocoa/ReactiveSwift/blob/3f4351d04115fd8797802d9b2d17b812cd761602/Sources/SignalProducer.swift#L2270-L2304
return SignalProducer { observer, lifetime in
func iterate(since lastSeenUserID: Int?) {
fetchUsers(since: lastSeenUserID)
.startWithSignal { (signal, signalDisposable) in
lifetime += signalDisposable
signal.observe { event in
switch event {
case .value(let users):
if let last = users.last, last.id < 300 {
// Emit the values we just got
observer.send(value: users)
// And get the next ones
iterate(since: last.id)
} else {
observer.sendCompleted()
}
case .failed(let error):
observer.send(error: error)
case .interrupted:
observer.sendInterrupted()
case .completed:
// Ignore completed events of the child streams
break
}
}
}
}
// Kick off the request for the first page
iterate(since: nil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment