2016-02-07 165 views
11

第一:这是我使用RxJs的第一个项目,我想我会通过使用它来学习最好的。RxJs可观察分页

我发现了这样的回答:Turning paginated requests into an Observable stream with RxJs 但它说,在注释:

你超过最大调用堆栈依然。大约有430页返回。我认为递归可能不是这里最好的解决方案

我想查询YouTube数据API,结果返回页面,我需要通过它们分页。 我想象像这样的工作流程可以工作: 1)发起呼叫 2)检查响应具有“nextPageToken这个” 3)如果有,做另一个请求到的Youtube API 4)如果不是,光洁度

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(这是否称为循环观察?)

- 这是正确的方法吗?

-Are'循环observable'是一件好事,他们甚至有可能吗?(我有问题创建一个)。

- 我应该先尝试其他方法吗?

- 是否有可能创建相互依赖的可观察流?

谢谢你的帮助。

回答

15

您正在过度复杂化这个问题,使用Rx.Observable.defer可以轻松解决问题。

想法是,您正在创建延迟observable(因此它将被创建并且仅在预订后才开始获取数据),并将其与同一个可观察值连接起来,但对于下一页将与下一页连接起来,以及等等...。所有这些都可以在没有递归的情况下完成。

下面是代码的外观:

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是函数接受一些参数和返回观察到的结果。它可以从库方法如下创建:

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此可观察项目没有延期(“懒惰”),所以它只会在某人订阅了它之后才开始提出请求,并且在您退订时停止。因此,如果您只需从流中“取”几个项目,只需要获取所需的页面(不是全部),请参阅答案中的代码示例。 –