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