问题
I am migrating some code from RestKit to Alamofire. I use MagicalRecord + AlamofireObjectMapper to map the JSON into CoreData objects.
I am now faced with the following situation:
My Data lives at this URL:
http://domain.com/api/resources?start=XX&limit=YY
Now I have to do this:
- Download the first page of data from a given URL using a page-size of
50
- If the number of loaded objects is equal to the page-size increment the
start
parameter by the page size - If the number is less than the page size combine all the loaded objects and return them to the callee.
In my previous non-Alamofire example I did use recursion for this but with PromiseKit I guess I have to do additional chaining of Promises rather than recursion of method calls.
So far I have only done simple chaining of Promises so the conditional looped chaining and how to implement this using PromiseKit is a bit of a mystery to me.
回答1:
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)
}
}
}
来源:https://stackoverflow.com/questions/38404047/promsiekit-alamofire-for-loading-paged-http-data