brainray brainray - 2 months ago 25
Objective-C Question

Using PromiseKit to force sequential download

I am using PromiseKit and would like to force sequential download of JSONs. The count of JSONs might change.

I have read this about chaining.
If I had a fixed number of say 3 downloads, this would be fine.

But what if I had a changing count of download that I would like to download sequentially?

This is my code for 2 URLs. I wonder how I could do this with

dateUrlArray[i]
iteration over the array?

- (void)downloadJSONWithPromiseKitDateArray:(NSMutableArray *)dateUrlArray {
[self.operationManager GET:dateUrlArray[0]
parameters:nil]
.then(^(id responseObject, AFHTTPRequestOperation *operation) {
NSDictionary *resultDictionary = (NSDictionary *) responseObject;
Menu *menu = [JsonMapper mapMenuFromDictionary:resultDictionary];
if (menu) {
[[DataAccess instance] addMenuToRealm:menu];
}
return [self.operationManager GET:dateUrlArray[1]
parameters:nil];
}).then(^(id responseObject, AFHTTPRequestOperation *operation) {
NSDictionary *resultDictionary = (NSDictionary *) responseObject;

Menu *menu = [JsonMapper mapMenuFromDictionary:resultDictionary];
if (menu) {
[[DataAccess instance] addMenuToRealm:menu];
}
})
.catch(^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self handleCatchwithError:error];
});
}).finally(^{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogInfo(@".....finally");
});
});
}

Answer

The concept you're looking for is thenable chaining. You want to chain multiple promises in a for loop.

My Objective-C is really rusty - but it should look something like:

// create an array for the results
__block NSMutableArray *results = [NSMutableArray arrayWithCapacity:[urls count]];
// create an initial promise
PMKPromise *p = [PMKPromise promiseWithValue: nil]; // create empty promise
for (id url in urls) {
    // chain
    p = p.then(^{
        // chain the request and storate
        return [self.operationManager GET:url
                parameters:nil].then(^(id responseObject, AFHTTPRequestOperation *operation) {
              [results addObject:responseObject]; // reference to result
              return nil; 
        });
    });
}
p.then(^{
    // all results available here
});