1

我正在将一些代码从 RestKit 迁移到 Alamofire。我使用 MagicalRecord + AlamofireObjectMapper 将 JSON 映射到 CoreData 对象。

我现在面临以下情况:

我的数据位于此 URL:

http://domain.com/api/resources?start=XX&limit=YY

现在我必须这样做:

  • 使用页面大小从给定 URL 下载数据的第一页50
  • 如果加载对象的数量等于页面大小,则将start参数增加页面大小
  • 如果数字小于页面大小,则合并所有加载的对象并将它们返回给被调用者。

在我之前的非 Alamofire 示例中,我确实为此使用了递归,但使用 PromiseKit 我想我必须做额外的 Promises 链接,而不是方法调用的递归。

到目前为止,我只完成了简单的 Promises 链接,所以条件循环链接以及如何使用 PromiseKit 实现它对我来说有点神秘。

4

1 回答 1

3

我确实想出了一种似乎效果很好的方法。但是,我觉得这可能更简洁,因此非常欢迎更好的答案或评论。

我决定将递归和 Promises 结合起来(由于缺乏更好的解决方案)。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)
                }
        }
    }
}

最后一个方法结合了传入的结果和当前加载的结果。如果到达页面末尾,则使用完整的承诺返回结果,如果需要加载更多页面,则再次调用第二种方法:

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)
        }
    }
}
于 2016-07-15T20:35:10.327 回答