Javascript RXJS扩展运算符
我正在做一个房地产网站,使用RETS 我试图从RETS服务器执行的查询是有限的,在循环中运行它,增加我的偏移量,直到我拥有所有数据。在运行查询并找到计数值之前,我不知道计数是多少 我曾尝试使用expand,但我不知道它到底是如何工作的。尝试了多种方法,甚至使用了旧的while循环,while不能使用.then方法。自从我在Angular 4中使用RXJS以来,我就转向了它 这是以快递方式完成的。我最终需要运行corn作业来获取更新的属性,但我的问题是获取所有数据,如果计数高于偏移量,则每次都增加偏移量。例如,运行一个偏移量为1、限制为500的查询。这里的总数是1690。所以下一步我的偏移量是:Javascript RXJS扩展运算符,javascript,rxjs,rets,Javascript,Rxjs,Rets,我正在做一个房地产网站,使用RETS 我试图从RETS服务器执行的查询是有限的,在循环中运行它,增加我的偏移量,直到我拥有所有数据。在运行查询并找到计数值之前,我不知道计数是多少 我曾尝试使用expand,但我不知道它到底是如何工作的。尝试了多种方法,甚至使用了旧的while循环,while不能使用.then方法。自从我在Angular 4中使用RXJS以来,我就转向了它 这是以快递方式完成的。我最终需要运行corn作业来获取更新的属性,但我的问题是获取所有数据,如果计数高于偏移量,则每次都增加
var offset = 1;
var limit = 500;
var list = new Promise(function (resolve, reject) {
rets.getAutoLogoutClient(config.clientSettings, (client) => {
var results = client.search.query(SearchType, Class, Query, {
limit: limit,
offset: offset
});
resolve(results);
});
});
var source = Rx.Observable.fromPromise(list);
source.subscribe(results => console.log(results.count));
一旦我有了数据,我需要将其保存到MongoDB。我已经成功地做到了。它只是想找到一种不用手动设置偏移量就能获取所有数据的方法
请注意,服务器限制为2500,是的,我可以一次获取所有这些数据,但也有其他数据,例如媒体,它们的数据量可能远远超过2500
有什么建议吗 这实际上是RxJS的一个相当常见的用例,因为有很多分页数据源,或者在一次可以请求的内容上受到限制的数据源 我的两分钱 在我看来,
expand
可能是最好的运算符,因为您正在对未知数据源进行分页,并且至少需要一个查询才能确定最终计数。如果您知道要查询多少数据,一个更简单的选择是使用类似于mergeScan
的东西,但我离题了
建议的解决方案
这可能需要一点努力才能让你的头脑清醒过来,所以我在任何可能的地方都添加了注释来分解这一切是如何工作的。注意,我还没有实际测试过这个,所以请原谅我的语法错误
offset += limit
//任何一个查询的常量限制
常数限值=500;
//RxJS帮助器方法,将异步调用包装成可观察的
//我是基于我所看到的你的样品,这使我相信
//这应该行得通。
const clientish=Rx.Observable.bindCallback(rets.getAutologotClient);
//围绕查询调用的方法包装器,用于包装结果承诺
//推迟。
常量queryish=(客户端,参数)=>
//注意这里使用defer是故意的,因为查询返回
//承诺将立即开始执行,这将阻止这种行为
//并在订阅时强制执行。
Rx.Observable.defer(()=>client.search.query(SearchType,Class,query,params));
//这就完成了实际的扩展功能
//注意,这是一个高阶函数,因为客户端和参数
//可在不同时间使用
常量扩展器=(客户端)=>({limit,count})=>
//调用查询方法
querysh(客户端,{limit,count})
//重新映射结果,更新偏移量、计数并转发整个
//包下游
.map(结果=>({
极限,
count:results.count,
偏移量:偏移量+限制,
结果
}));
//通过构造客户端启动流
clientish(config.clientSettings)
.switchMap(客户端=>
//这是初始调用的参数
Rx.Observable.of({极限,偏移量:0})
//使用客户端调用expander函数
//第二个参数是最大并发性,如果需要,您可以更改它
.扩展(扩展器(客户端),1)
//Expand将继续递归,除非您告诉它停止
//一旦偏移量超过计数,这将停止执行,即
//所有数据
.takeWhile(({count,offset})=>offset/*使用结果做一些事情*/);
这就是我在这里尝试过的东西。我仍然在调整这个过程中。所以我想做的是进一步细分searchQuery。我不确定我是否应该经过observer.next,所以我要弄清楚在再次安装返回的searchQuery之前映射和执行的位置。我不确定takeUntil是否会接受正确或错误的答案。我所需要做的就是将这些数据保存到mongodb中。所以我想我可以像这样把我的save方法放在那里,但我还是想弄明白这一点
注意:当还有更多数据时,results.maxRowsExceeded返回true。因此,一旦maxRows返回false,它将停止,并且所有数据都已提取。这不起作用。switchMap不是一个函数。takeWhile有语法错误,需要更好地组合rets客户端内容。@JoshuaScott您使用的是哪个版本的RxJS?我使用的是RxJS 5
// Your constant limit for any one query
const limit = 500;
// RxJS helper method that wraps the async call into an Observable
// I am basing this on what I saw of your sample which leads me to believe
// that this should work.
const clientish = Rx.Observable.bindCallback(rets.getAutoLogoutClient);
// A method wrapper around your query call that wraps the resulting promise
// into a defer.
const queryish = (client, params) =>
// Note the use of defer here is deliberate, since the query returns
// a promise that will begin executing immediately, this prevents that behavior
// And forces execution on subscription.
Rx.Observable.defer(() => client.search.query(SearchType, Class, Query, params));
// This does the actual expansion function
// Note this is a higher order function because the client and the parameters
// are available at different times
const expander = (client) => ({limit, count}) =>
// Invoke the query method
queryish(client, {limit, count})
// Remap the results, update offset and count and forward the whole
// package down stream
.map(results => ({
limit,
count: results.count,
offset: offset + limit,
results
}));
// Start the stream by constructing the client
clientish(config.clientSettings)
.switchMap(client =>
// This are the arguments for the initial call
Rx.Observable.of({limit, offset: 0})
// Call the expander function with the client
// The second argument is the max concurrency, you can change that if needed
.expand(expander(client), 1)
// Expand will keep recursing unless you tell it to stop
// This will halt the execution once offset exceeds count, i.e. you have
// all the data
.takeWhile(({count, offset}) => offset < count)
// Further downstream you only care about the results
// So extract them from the message body and only forward them
.pluck('results')
)
.subscribe(results => /*Do stuff with results*/);
const retsConnect = Rx.Observable.create(function(observer) {
rets.getAutoLogoutClient(config.clientSettings, client => {
return searchQuery(client, 500, 1, observer);
});
});
function searchQuery(client, limit, offset, observer) {
let currentOffset = offset === undefined || offset === 0 ? 1 : offset;
return client.search.query(SearchType, Class, Query, {limit: limit, offset: currentOffset})
.then(results => {
offset += limit;
observer.next(results.maxRowsExceeded);
if (results.maxRowsExceeded) {
console.log(offset);
return searchQuery(client, limit, offset, observer);
} else {
console.log('Completed');
observer.complete();
}
});
}
retsConnect.subscribe(val => console.log(val));