2016-02-07 13 views
11

最初:これは私がRxJsを使用している最初のプロジェクトです。私はそれを使ってベストだと思っていました。RxJs Observable Pagination

私はこの答えが見つかりました:Turning paginated requests into an Observable stream with RxJs をしかし、それはコメントで述べている:

あなたはまだ最大コールスタックを超えています。約430ページが返されました。私は再帰がここで最善の解決策ではないかもしれないと思う。

私はYoutube Data APIをクエリしたいが、結果はページに戻ってくるので、それらを改ページする必要がある。 私はこのような作業の流れは、仕事ができる想像: 1)コール 2を開始します)、それは、YouTubeのAPI 4に別のリクエストを行うた場合、応答が) 3「nextPageToken」を持っているかどうかを確認してください)でない場合は、仕上げ

So to do this I could Imagine the following Observables/streams: 
FirstRequestStream -A-X---------------> 
ResponseStream  -A-A-A-A--X--------> 
RequestStream  -I-A-I-A-----------> 
A = Action 
I = Info from upper stream 
X = Termination 

(この図は、私はそれを作った方法正しいかどうかわからない)

のでResponseStreamはFirstRequestStreamとRequestStream(マージ機能を使用して)に依存します。 RequestStreamはResponseStreamに依存します(これは循環観測と呼ばれますか?)

- これは正しいアプローチですか?

- 「循環する観察可能性」は良いことですか、それらも可能ですか(私は問題を作りました)。

- 私は最初に試してみてください。

- 相互依存の観測可能なストリームを作成することは可能ですか?

ありがとうございました。

答えて

15

あなたはこの問題を複雑にしています。Rx.Observable.deferを使用すると簡単に解決できます。

アイデアは、遅延オブザーバブルを作成しているため(作成され、サブスクリプション後にデータを取得し始めます)、同じオブザーバブルで連結しますが、次のページでも連結されます。そうです...。そしてそのすべては再帰なしで行うことができます。ここで

は、コードがどのように見えるかです:

function fetchItems(params, pageToken) { 
    return Observable.defer(
    () => fetchSomething({ 
     params, 
     pageToken, 
    }) 
     .flatMap(({ items, nextPageToken }) => { 
     const items$ = Observable.fromArray(items); 
     const next$ = nextPageToken 
      ? fetchItems(params, nextPageToken) 
      : Observable.empty(); 

     return Observable.concat(
      items$, 
      next$ 
     ); 
     }) 
); 
} 

const items$ = fetchItems(params) 
    // process all items until end 

const firstTenItems$ = fetchItems(params) 
    .take(10); 
    // process only first 10 items, without fetching all of the data 

fetchSomethingは、いくつかのparamsを受け入れ、結果の観測可能返す関数です。

import {Observable} from 'rx'; 
import google from 'googleapis'; 

const yt = google.youtube({ 
    version: 'v3', 
    auth: // your apiKey here, 
}); 

const getChannel = Observable.fromNodeCallback(yt.channels.list, yt, r=>r); 
+0

しかし、私が理解しているように、これは、誰も結果に興味がないならば、すべての改ページされた呼び出しを7つにするでしょう。例えば、ユーザーが "次へページの "ボタン、"無限のスクロール "を完了しました。このようなことを可能にするために、どのようにこのロジックを修正することができますか? –

+0

@torazaburoいいえこの観測可能なものは延期されています( "lazy")ので、誰かが購読した後にのみ要求を開始し、購読を停止すると停止します。したがって、ストリームからいくつかのアイテムを "取る"場合、必要なページだけがフェッチされます(すべてではありません)。答えのコード例を参照してください。 –