Продолжайте откладывать HTTP-запрос до тех пор, пока не поступят новые параметры

Предположим, у нас есть функция getIds(), которая принимает массив некоторых идентификаторов, например:

getIds([4, 1, 32]);

Эта функция задержит вызов HTTP на 100 мс. Но в течение 100 мс, если эта же функция будет вызвана снова:

getIds([1, 8, 5]);

Он сбросит таймер 100 мс и продолжит объединение переданных идентификаторов. Он отправит HTTP-запрос только в том случае, если его никто не вызывал более 100 мс.

Я новичок в RxJS, и вот моя попытка решить эту проблему, но у меня есть ощущение, что для этой проблемы может быть лучшее решение.

https://jsfiddle.net/iFadey/v3v3L0yd/2/

function getIds(ids) {
  let observable = getIds._observable,
      subject = getIds._subject;

  if (!observable) {
    subject = getIds._subject = new Rx.ReplaySubject();
    observable = getIds._observable = subject
      .distinct()
      .reduce((arr, id) => {
        arr.push(id);
        return arr;
      }, [])
      // Some HTTP GET request will go here
      // whose results may get flatMapped here
      .publish()
      .refCount()
      ;
  }

  ids.forEach((id) => {
    console.log(id);
    subject.next(id);
  });

  clearTimeout(getIds._timer);
  getIds._timer = setTimeout(() => {
    getIds._observable = null;
    getIds._subject = null;
    subject.complete();
  }, 100);

  return observable;
}

getIds([1, 2, 3])
.subscribe((ids) => {
  console.log(ids);
});

getIds([3, 4, 5])
.subscribe((ids) => {
  console.log(ids);
});

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


person ifadey    schedule 01.06.2016    source источник


Ответы (1)


Я не уверен, что точно уловил, что из следующего вы ищете, поэтому я просто опишу оба. По моему опыту, есть два «шаблона, основанных на времени», которые чаще всего подходят для этого типа проблем:

  • отклонить

URL-адрес rxmarbles: http://rxmarbles.com/#debounce ; документ github

Как говорится в его документации, это

Испускает элемент из исходного Observable по прошествии определенного промежутка времени, при этом Observable не пропускает какие-либо другие элементы.

  • дроссель

URL-адрес rxmarbles: пока нет; документ github

Возвращает Observable, который испускает только первый элемент, испускаемый исходным Observable в течение последовательных окон времени заданной продолжительности.

По сути, если вы хотите подождать, пока входные сигналы не затихнут в течение определенного периода времени, прежде чем предпринимать какие-либо действия, вам нужно устранить дребезг. Если вы совсем не хотите ждать, но не хотите делать более 1 запроса в течение определенного периода времени, вам нужно дросселировать.

Надеюсь, это имеет смысл.

person Ben Dadsetan    schedule 26.07.2016
comment
Спасибо за ответ, но я не искал этих операторов. Мне нужен оператор, который ведет себя так же, как debounce, но без сброса предыдущих значений. Вместо этого он должен поставить их в очередь. Я думаю, что мой вопрос немного расплывчатый. Позвольте мне отредактировать его. - person ifadey; 29.07.2016