I did come up with an approach that seems to work fine. However, I have the feeling that this could be much more concise so better answers or comments are very welcome.
I decided to combine recursion and Promises (due to a lack of better solutions). So I am passing along a currentPromise
which is chained further as more pages need to be loaded.
The first method simply starts the whole process and the created Promise is instantly fulfilled with an empty array like so: Promise([Issue]())
:
func loadAllPagedIssues(repository: Repository) -> Promise<[Issue]>{
return loadPagedIssues(repository, limit: Config.apiPageSize, start: 0, currentPromise: Promise([Issue]()))
}
The next method does the actual work of downloading the content and parsing it.
func loadIssues(url: String, repository: Repository) -> Promise<[Issue]>{
return Promise{ fullfill, reject in
self.manager
.request(.GET, url, headers: self.headers)
.responseArray(keyPath: "issues", context: repository) { (response: Response<[Issue], NSError>) in
switch response.result{
case .Success(let value):
fullfill(value)
case .Failure(let e):
reject(e)
}
}
}
}
The final method combines the results being passed in and the currently loaded ones. If the end of the page is reached then the results are returned using a fullfilled promise and if more pages need to be loaded then another call to the second method is issued:
func loadPagedIssues(repository: Repository, limit: Int, start: Int, currentPromise: Promise<[Issue]>) -> Promise<[Issue]>{
let url = baseURL + Config.pagedIssuesPath.replaceTokens(
[
"repo": repository.slug,
"limit": String(limit),
"start": String(start)
]
)
let loadPromise = self.loadIssues(url, repository: repository)
return when(loadPromise, currentPromise).then{ newIssues, existingIssues -> Promise<[Issue]> in
let combined = Promise<[Issue]>(newIssues + existingIssues)
if newIssues.count < limit{
// Reached the end of the page
return combined
} else {
return self.loadPagedIssues(repository, limit: limit, start: (start + limit), currentPromise: combined)
}
}
}