PromsieKit + Alamofire用于加载分页的HTTP数据

时间:2016-07-15 19:46:50

标签: swift macos core-data alamofire promisekit

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

我现在面临以下情况:

我的数据位于以下网址:

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

现在我必须这样做:

  • 使用页面大小50
  • 从给定网址下载第一页数据
  • 如果加载的对象数等于页面大小,则start参数按页面大小增加
  • 如果该数字小于页面大小,则组合所有已加载的对象并将其返回给被调用者。

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

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

1 个答案:

答案 0 :(得分:2)

我确实提出了一种似乎工作正常的方法。但是,我觉得这可以更加简洁,因此非常欢迎更好的答案或评论。

我决定结合递归和Promises(由于缺乏更好的解决方案)。所以我传递的是currentPromise,因为需要加载更多的页面,所以Promise([Issue]())会被进一步链接。

第一种方法只是启动整个过程,并且使用如下的空数组立即实现创建的Promise: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)
        }
    }
}

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

dgvList[colIndex, rowIndex].Value