Rxjs 可观测数据和获取分页数据?

Rxjs 可观测数据和获取分页数据?,rxjs,Rxjs,我需要创建一个可观察的,我可以从中“提取”数据,以使用可分页的api。我每个请求只能获取100个项目,我希望能够使用observable作为生成器函数(在该函数上我可以调用.next()来发出获取下100个项目的请求)。 不幸的是,我找不到一种方法来使用Rx。我想这可能是使用受控可观测或主体。你们能给我举个例子吗 到目前为止,我得到的是: function list(entityType, viewName, fetchAll = false) { var skip = 0,

我需要创建一个可观察的,我可以从中“提取”数据,以使用可分页的api。我每个请求只能获取100个项目,我希望能够使用observable作为生成器函数(在该函数上我可以调用
.next()
来发出获取下100个项目的请求)。 不幸的是,我找不到一种方法来使用Rx。我想这可能是使用受控可观测或主体。你们能给我举个例子吗

到目前为止,我得到的是:

function list(entityType, viewName, fetchAll = false) {
    var skip = 0,
        total = 0;

    const subject = new Rx.Subject(),
        response$ = subject
        .takeWhile(() => skip <= total)
        .startWith(skip)
        .flatMap((skip) => fetchPagePromise(skip)),

        next = () => subject.onNext(skip);

    if (fetchAll) {
        Rx.Observable.timer(100, 100).subscribe(() => next());
    }

    return {
        data$: response$.map(response => response),
        next: fetchAll === true ? undefined : next
    };

    function fetchPagePromise() {
        let limit = 100,
            obj = {
                viewName, limit, skip
            },
            qs = objectToQueryString(obj);

        return $http.get(`${apiBase}/api/data/${entityType}${qs}`).then((res) => {
            total = res.data.Total;
            skip += limit;

            return res.data.Rows;
        });
    }
}
函数列表(entityType、viewName、fetchAll=false){
var skip=0,
总数=0;
const subject=new Rx.subject(),
答复$=主题
.takeWhile(()=>跳过fetchPagePromise(跳过)),
next=()=>subject.onNext(跳过);
如果(全部){
Rx.Observable.timer(100100).subscribe(()=>next());
}
返回{
数据$:响应$.map(响应=>响应),
下一步:fetchAll==true?未定义:下一步
};
函数fetchPagePromission(){
设极限=100,
obj={
视图名称、限制、跳过
},
qs=objectToQueryString(obj);
返回$http.get(`${apiBase}/api/data/${entityType}${qs}`)。然后((res)=>{
总计=res.data.total;
跳过+=限制;
返回res.data.Rows;
});
}
}

这有点像一个生成器。它返回一个可观察的和
next
处理程序。每当调用
next
时,它都会从api中提取下100个项并推入可观察项。另外,如果传递了第三个参数
fetchAll
,那么它将继续提取数据,直到没有更多数据为止。虽然re是函数闭包中的两个变异变量-
skip
total
,我不知道在异步/不可预测的环境中这样管理它们是否合适。

您通常希望避免的事情之一是尝试将Rx变成一个普通的旧事件发射器。通常,当您尝试并仅触发
时,它是一个指示器>通过传递
受试者
观察者界面,手动观察

你应该问问自己,我的数据来自哪里?什么调用了
next()
,什么调用了next(),等等。在这些调用足够多之后,你通常会发现这将引导你找到可以被
可观察的
直接包装的东西,而不是显式调用
next()
。此外,我认为
fetchAll
标志实际上应该保留在外部。您只需传入一个标志,就可以将接口本质上变成一个void方法,这只会让接口变得混乱

因此,我建议进行如下重构:

Rx.Observable.prototype.lazyRequest = function(entityType, viewName, limit = 100) {
  var source = this;
  return Rx.Observable.create(obs => {
    var response = source
                     //Skip is really just the (limit * index) 
                     .map((x, i) => i * limit)
                     .flatMap((skip) => {
                               let obj = {viewName, skip, limit},
                                   qs = objectToQueryString(obj);

                               //Handle promises implicitly
                               return $http.get(`${apiBase}/api/data/${entityType}${qs}`);
                              },
                              //Return this with our skip information
                              (skip, res) => {skip, res})
                     //Publish it so the stream get shared.
                     .publish();

    //This will emit once once you are out of data
    var stop = response.first(x => x.skip >= x.res.data.Total);

    return new CompositeDisposable(
      //Complete this stream when stop emits
      response.takeUntil(stop)
              //Downstream only cares about the data rows
              .map(x => x.res.data.Rows)
              .subscribe(obs),
      //Hook everything up
      response.connect());

  });

}
然后您可以这样使用它:

//An example of a "starting point", a button click
//Update the rows every time a new event comes through
Rx.Observable.fromEvent($button, 'click')
             .startWith(0) //Inject some data into the pipeline
             .lazyRequest(entityType, viewName)
             .subscribe(/*Do something with the returned rows*/);

//Get all of the rows, will keep hitting the endpoint until it completes
Rx.Observable.interval(100)
             .lazyRequest(entityType, viewName)
             //Gather all the values into an array and emit that.
             .toArray()
             .subscribe();

你能提供一个你尝试过的例子吗?你打算如何触发下一个
请求?你的可分页api是什么样子的?@paulpdaniels我包括了一个代码片段