2015-06-07 7 views
5

Ich verwende PromiseKit und möchte den sequentiellen Download von JSONs erzwingen. Die Anzahl der JSONs könnte sich ändern.Verwenden von PromiseKit, um sequentiellen Download zu erzwingen

Ich habe this über Verkettung gelesen. Wenn ich eine feste Anzahl von sagen 3 Downloads hätte, wäre das in Ordnung.

Aber was wäre, wenn ich eine wechselnde Anzahl von Downloads hätte, die ich nacheinander herunterladen möchte?

Dies ist mein Code für 2 URLs. Ich frage mich, wie ich das mit dateUrlArray[i] Iteration über das Array tun könnte?

- (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"); 
     }); 
    }); 
} 

Antwort

4

Das Konzept, das Sie suchen, ist then fähige Verkettung. Sie möchten mehrere Versprechen in eine for-Schleife ketten.

Meine Objective-C ist wirklich rostig - aber es sollte wie aussehen:

// 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 
}); 
+0

Vielen vielen Dank für das 'rostige' ObjC ;-) Tolle Antwort und IMHO eine Unterlassung auf der Promisekit-Site. Ich habe einen kleinen Schnitt gemacht (p sollte vom Typ PMKPromise sein). – brainray

3

Für diejenigen von uns für eine Swift 2.3 Lösung suchen:

import PromiseKit 

extension Promise { 
    static func resolveSequentially(promiseFns: [()->Promise<T>]) -> Promise<T>? { 
     return promiseFns.reduce(nil) { (fn1: Promise<T>?, fn2: (()->Promise<T>)?) -> Promise<T>? in 
      return fn1?.then({ (_) -> Promise<T> in 
       return fn2!() 
      }) ?? fn2!() 
     } 
    } 
} 

Beachten Sie, dass diese Funktion gibt nil zurück, wenn das Array "Versprechungen" leer ist.

Anwendungsbeispiel

Unten ist ein Beispiel dafür, wie eine Reihe von Anhängen in Folge laden:

func uploadAttachments(attachments: [Attachment]) -> Promise<Void> { 
    let promiseFns = attachments.map({ (attachment: Attachment) -> (()->Promise<Void>) in 
     return { 
      return self.uploadAttachment(attachment) 
     } 
    }) 
    return Promise.resolveSequentially(promiseFns)?.then({}) ?? Promise() 
} 

func uploadAttachment(attachment: Attachment) -> Promise<Void> { 
    // Do the actual uploading 
    return Promise() 
} 
+0

Vielen Dank für die Eingabe! BTW: Inzwischen löse ich diese Art von Aufgaben mit NSOperation, die keine externe Bibliothek benötigt. – brainray

+0

Danke für das Feedback, das macht total Sinn! – Vegard

2

Dank für Vegard Antwort und ich umschreiben für Swift 3:

extension Promise { 
    static func resolveSequentially(promiseFns: [()->Promise<T>]) -> Promise<T>? { 
     return promiseFns.reduce(nil) { (fn1: Promise<T>?, fn2: (()->Promise<T>)?) -> Promise<T>? in 
      return fn1?.then{ (_) -> Promise<T> in 
       return fn2!() 
      } ?? fn2!() 
     } 
    } 
} 



/* Example */ 
func uploadAttachments(_ attachments: [Attachment]) -> Promise<Void> { 
    let promiseFns = attachments.map({ (attachment: Attachment) -> (()->Promise<Void>) in 
     return { 
      return self. uploadAttachment(attachment) 
     } 
    }) 

    return Promise.resolveSequentially(promiseFns: promiseFns)?.then{Void -> Void in} ?? Promise { Void -> Void in } 
} 
Verwandte Themen