私はうまくいくと思われるアプローチを思いつきました。ただし、これはもっと簡潔になる可能性があると感じているので、より良い回答やコメントは大歓迎です。
再帰と Promise を組み合わせることにしました (より良い解決策がないため)。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)
}
}
}
}
最後のメソッドは、渡された結果と現在読み込まれている結果を結合します。ページの終わりに達した場合は、満たされたプロミスを使用して結果が返され、さらにページをロードする必要がある場合は、2 番目のメソッドへの別の呼び出しが発行されます。
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)
}
}
}