WedX - журнал о программировании и компьютерных науках

Оператор расширения RXJS

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, запускается в цикле, увеличивая мое смещение, пока у меня не будут все мои данные. Я не знаю, что такое счет, пока не запущу запрос и не найду значение счетчика.

Я пытался использовать расширение, но я понятия не имею, как именно это работает. Пытался сделать это несколькими способами, даже используя старый цикл while, который пока не работает с методом .then. Поэтому я обратился к RXJS, так как использовал его в Angular 4.

Делается это экспрессом. В конечном итоге мне нужно запустить задания кукурузы для получения обновленных свойств, но моя проблема заключается в извлечении всех данных и увеличении смещения каждый раз, если счетчик превышает мое смещение. Так, например, запустите запрос со смещением 1 с ограничением 500. Всего здесь 1690. Итак, следующий обход моего смещения будет:

offset += limit

Когда у меня есть данные, мне нужно сохранить их в MongoDB. Что мне уже удалось успешно сделать. Это просто поиск способа получить все данные без необходимости вручную устанавливать мое смещение.

Обратите внимание, что предел сервера составляет 2500, да, я могу получить все это за один раз, но есть и другие данные, такие как медиа, которые могут иметь более 2500.

Какие-либо предложения?

04.07.2017

Ответы:


1

На самом деле это довольно распространенный вариант использования 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*/);
04.07.2017
  • Это не работает. switchMap не является функцией. У takeWhile есть синтаксические ошибки, но клиентский материал rets должен быть лучше скомбинирован. 05.07.2017
  • @JoshuaScott, какую версию RxJS вы используете? 05.07.2017
  • Я использую RXJS 5 05.07.2017

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

    Так что это где-то с тем, что я пробовал здесь. Я все еще в процессе настройки этого. Итак, что я хочу сделать, так это разбить поисковый запрос на более мелкие части. Не уверен, что мне следует передавать тудаObserver.Next, поэтому я собираюсь выяснить, где сопоставить и установить takeUntil, чтобы снова вернуть searchQuery. Я не уверен, что takeUntil примет значение true или false. Все, что мне нужно сделать, это сохранить эти данные в mongodb. Так что, я думаю, я мог бы оставить все как есть и добавить туда свой метод сохранения, но мне все равно нравится это выяснять.

    Примечание: results.maxRowsExceeded возвращает значение true, если данных еще больше. Поэтому, как только maxRows вернет false, он остановится, и все данные будут получены.

    05.07.2017
    Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]