我确实想出了一种似乎效果很好的方法。但是,我觉得这可能更简洁,因此非常欢迎更好的答案或评论。
我决定将递归和 Promises 结合起来(由于缺乏更好的解决方案)。currentPromise
因此,当需要加载更多页面时,我将传递一个进一步链接的内容。
第一种方法简单地启动整个过程,创建的 Promise 立即用一个空数组实现,如下所示Promise([Issue]())
:
func loadAllPagedIssues(repository: Repository) -> Promise<[Issue]>{
return loadPagedIssues(repository, limit: Config.apiPageSize, start: 0, currentPromise: Promise([Issue]()))
}
下一个方法执行下载内容和解析它的实际工作。
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)
}
}
}
}
最后一个方法结合了传入的结果和当前加载的结果。如果到达页面末尾,则使用完整的承诺返回结果,如果需要加载更多页面,则再次调用第二种方法:
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)
}
}
}