PagedIterableのメモ

概要

PagedIterableのコードを確認したため、備忘録として残しておきます。

PagedIterableは、 マイクロソフトのライブラリにおいて定義されているページング処理を行うためのクラスです。

使い方

iteratorを使用することで、ページ毎にアクセスできるようになっています。

 val iterator = hogeClient.listHoges.byPage().iterator()
 while (true) {
        if (!iterator.hasNext()) break
                val page = iterator.next()
 }

また、foreachやmap, flatMap等を使用することで全ての結果を一度に取得することもできます。

 val result = hogeClient.listHoges.byPage().flatMap { // do something }

byPage()を呼ぶ時呼ばない時の挙動の違い

byPage()による違いが気になったので、少しコードを追ってみました。

結論

結論としては、

  • byPageを呼ぶ...pageIdを用いて取得したページの値(リスト)をPagedResponseとして返却します。次のnext()でも、次ページを取得&返却します。
  • byPageを呼ばない...ページ毎に取得すること自体は変わりません。しかし、1ページ分の値を取得し、そのレスポンスの中のアイテムを一つずつ返却します。1ページの中のアイテムを返し終わった後、次のページを取得する流れで処理が進みます。

コードの内容

コード内の主な登場人物は

  • PagedIterable
  • PagedResponseIterable
  • PageItemIterator
  • PagedResponseIterator

の4つです。

byPageを使用する場合の動作

  1. ClientクラスのlistHoge()がpagedIterableを返却する。
  2. byPage()がPagedResponseIterableを返却する
  3. PagedResponseIterableのiterator()がPageResponseIteratorを返却する
  4. PageResponseIterator#next()を呼び、実際のページ取得処理が始まる。
  5. 取得結果からpageIdを取得し、保存する。
  6. 次のnext()で、同pageIdを使用して後続のページを取得する。 という流れになっています。

byPage()を使用せず、pagedIterable#iteratorを呼ぶ場合の動作

  1. PagedIterable#iterator()を呼び、PageItemIteratorを生成する。
  2. PageItemIteratorの引数として、PagedIterable#byPage()#iteratorを呼び、渡す。 (結局、byPageは呼ばれている)
  3. PageResponseIterator#next()を呼び、実際のページ取得処理が始まる。
  4. 取得結果をDequeに入れる
  5. 取得結果からpageIdを取得し、保存する。
  6. Dequeに値があればpopする
  7. 次のnext()で、Dequeに値があればpopする。Dequeが空であればpageIdを使用して後続のページを取得する。

という流れになっています。

byPageという名前の通り、 page毎の値を返すか、アイテム一つずつを返すかの違いになっているようです。