我有一项返回页面中数据的服务。对一页的响应包含有关如何查询下一页的详细信息。
我的方法是返回响应数据,然后在有更多页面可用时立即将延迟的调用连接到相同的可观察序列。
function getPageFromServer(index) {
// return dummy data for testcase
return {nextpage:index+1, data:[1,2,3]};
}
function getPagedItems(index) {
return Observable.return(getPageFromServer(index))
.flatMap(function(response) {
if (response.nextpage !== null) {
return Observable.fromArray(response.data)
.concat(Observable.defer(function() {return getPagedItems(response.nextpage);}));
}
return Observable.fromArray(response.data);
});
}
getPagedItems(0).subscribe(
function(item) {
console.log(new Date(), item);
},
function(error) {
console.log(error);
}
)
这肯定是错误的方法,因为在2秒钟之内您将获得:
throw e;
^
RangeError: Maximum call stack size exceeded
at CompositeDisposablePrototype.dispose (/Users/me/node_modules/rx/dist/rx.all.js:654:51)
分页的正确方法是什么?
最佳答案
编辑啊!我看到了您所面临的问题。进行一些尾部调用优化可以解决您的问题:
function mockGetPageAjaxCall(index) {
// return dummy data for testcase
return Promise.resolve({nextpage:index+1, data:[1,2,3]});
}
function getPageFromServer(index) {
return Observable.create(function(obs) {
mockGetPageAjaxCall(index).then(function(page) {
obs.onNext(page);
}).catch(function(err) {
obs.onError(err)
}).finally(function() {
obs.onCompleted();
});
});
}
function getPagedItems(index) {
return Observable.create(function(obs) {
// create a delegate to do the work
var disposable = new SerialDisposable();
var recur = function(index) {
disposable.setDisposable(getPageFromServer(index).retry().subscribe(function(page) {
obs.onNext(page.items);
if(page.nextpage === null) {
obs.onCompleted();
}
// call the delegate recursively
recur(page.nextpage);
}));
};
// call the delegate to start it
recur(0);
return disposable;
});
}
getPagedItems(0).subscribe(
function(item) {
console.log(new Date(), item);
},
function(error) {
console.log(error);
}
)
关于javascript - 使用RxJ将分页的请求转换为可观察的流,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27514310/