【问题标题】:Using PromiseKit to force sequential download使用 PromiseKit 强制顺序下载
【发布时间】:2015-08-21 21:58:01
【问题描述】:

我正在使用 PromiseKit,并希望强制顺序下载 JSON。 JSON 的数量可能会发生变化。

我已经阅读了this 关于链接的内容。 如果我有固定数量的下载量,比如 3 次,那就没问题了。

但是,如果我想按顺序下载不断变化的下载次数怎么办?

这是我的 2 个 URL 的代码。我想知道如何通过数组上的dateUrlArray[i] 迭代来做到这一点?

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

【问题讨论】:

    标签: ios objective-c promise promisekit


    【解决方案1】:

    感谢 Vegard 的回答,我为 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 }
    }
    

    【讨论】:

      【解决方案2】:

      对于我们这些正在寻找 Swift 2.3 解决方案的人:

      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!()
              }
          }
      }
      

      请注意,如果 promises 数组为空,此函数将返回 nil

      使用示例

      以下是如何按顺序上传附件数组的示例:

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

      【讨论】:

      • 非常感谢您的意见!顺便说一句:同时我用 NSOperation 解决这类任务 wgich 不需要第三方库
      • 感谢您的反馈,这完全有道理!
      【解决方案3】:

      您正在寻找的概念是thenable 链接。你想在一个 for 循环中链接多个 Promise。

      我的 Objective-C 确实生锈了 - 但它应该看起来像:

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

      【讨论】:

      • 非常感谢那个“生锈”的 ObjC ;-) 很好的答案,恕我直言,Promisekit 网站上的遗漏。我做了一个小编辑(p 应该是 PMKPromise 类型)。
      猜你喜欢
      • 2010-12-05
      • 2013-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 2012-05-21
      相关资源
      最近更新 更多