1

一部のコードを RestKit から Alamofire に移行しています。MagicalRecord + AlamofireObjectMapper を使用して、JSON を CoreData オブジェクトにマップします。

私は今、次のような状況に直面しています。

私のデータは次の URL にあります。

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

今、私はこれをしなければなりません:

  • のページサイズを使用して、指定された URL からデータの最初のページをダウンロードします50
  • ロードされたオブジェクトの数が page-size と等しい場合、startパラメータをページサイズだけインクリメントします。
  • 数がページ サイズよりも小さい場合は、読み込まれたすべてのオブジェクトを結合して呼び出し先に返します。

以前の Alamofire 以外の例では、これに再帰を使用しましたが、PromiseKit では、メソッド呼び出しの再帰ではなく、Promise の追加の連鎖を行う必要があると思います。

これまでのところ、Promise の単純な連鎖しか行っていないため、条件付きループ連鎖と、PromiseKit を使用してこれを実装する方法は、私にとって少し謎です。

4

1 に答える 1

3

私はうまくいくと思われるアプローチを思いつきました。ただし、これはもっと簡潔になる可能性があると感じているので、より良い回答やコメントは大歓迎です。

再帰と Promise を組み合わせることにしました (より良い解決策がないため)。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)
                }
        }
    }
}

最後のメソッドは、渡された結果と現在読み込まれている結果を結合します。ページの終わりに達した場合は、満たされたプロミスを使用して結果が返され、さらにページをロードする必要がある場合は、2 番目のメソッドへの別の呼び出しが発行されます。

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 に答える