RXJS扩展运营商

时间:2017-07-04 03:29:30

标签: javascript rxjs rets

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));

我正在使用RETS做房地产网站。

我正在尝试进行的查询仅限于RETS服务器,在循环中运行此操作会增加我的偏移量,直到我拥有所有数据。在运行查询并找到计数值之前,我不知道计数是什么。

我试过使用扩展,但我不知道它究竟是如何工作的。试图做这些多种方式,甚至使用旧的时尚循环,虽然没有使用.then方法。所以我已经转向RXJS,因为我在Angular 4中使用它。

这是在快递中完成的。我需要最终运行corn作业来获取更新的属性,但我的问题是获取所有数据并且每次增加偏移量,如果计数高于我的偏移量。因此,例如,运行一个偏移量为1且限制为500的查询。总计这里是1690.所以接下来绕过我的偏移量将是:

offset += limit

获得数据后,我需要将其保存到MongoDB。我已经成功做到了。它只是找到一种获取所有数据的方法,而无需手动设置我的偏移量。

请注意,服务器限制为2500,是的,我可以一次性获取所有这些,但也有其他数据,例如媒体,可能超过2500.

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

这实际上是RxJS的一个相当常见的用例,因为有很多分页数据源,或者在您可以同时请求的内容中限制的来源。

我的两分钱

在我看来,expand可能是最好的操作符,因为您要对未知数据源进行分页,并且至少需要一个查询才能确定最终计数。如果你知道要查询多少数据,那么使用mergeScan之类的东西就更容易了,但我离题了。

提议的解决方案

这可能需要花费一些力气来包围你,所以我尽可能地添加了注释来分解这一切是如何工作的。 注意我实际上没有测试过这个,所以请原谅我任何语法错误。

// 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*/);

答案 1 :(得分:0)

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));

所以这是我在这里尝试过的地方。我还在调整这个。所以我要做的是更多地打破searchQuery。不知道我是否应该在那里传递observer.next,所以我要弄清楚在哪里映射并重新安装返回searchQuery。我不确定takeUntil会采取真或假的方式。我只需要将这些数据保存到mongodb中。所以我想我可以这样离开它并将我的保存方法放在那里,但我仍然想知道这一点。

注意:当还有更多数据时,results.maxRowsExceeded返回true。因此,一旦maxRows返回false,它将停止并且所有数据都已被提取。