Rx Js dynamici c длительность throttleTime aka получить поток событий запуска прокрутки - PullRequest
1 голос
/ 26 апреля 2020

Здравствуйте,

Прежде всего, спасибо, что прочитали это. 100

Я хочу обработать поток событий прокрутки и хочу реагировать на запуск прокрутки и игнорировать последующую серию событий прокрутки, пока поток не будет считаться неактивным (ограничение по времени). Поэтому после задержки я хочу повторить то же самое.

Это мое решение до сих пор:

    import { fromEvent } from 'rxjs';
    import { throttle, debounceTime } from 'rxjs/operators';

    const stream = fromEvent(window, 'scroll');
    const controllerStream = stream.pipe(debounceTime(500));

    this.sub = stream
      .pipe(
        throttle(() => controllerStream, {
          leading: true,
          trailing: false,
        })
      )
      .subscribe(() => {
        // react on scroll-start events
      });

Есть ли лучший способ? Я рассматривал такие операторы, как throttleTime, debounce, debounceTime ... но я не смог найти конфигурацию, соответствующую моим потребностям

Спасибо ??

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Я сделал третью версию, инкапсулируя свое решение в пользовательский оператор на основе ответа @backtick. Есть ли проблема с этим решением? Утечка памяти или что-то? Я не уверен, будет ли внутренний controllerStream уничтожать должным образом или вообще.

const firstAfterInactiveFor = (ms) => (source) => {
 const controllerStream = source.pipe(debounceTime(ms));
  return source
  .pipe(
    throttle(() => controllerStream, {
      leading: true,
      trailing: false
    })
  )
};

// This achieves the desired behavior.
stream
  .pipe(
    firstAfterInactiveFor(500)
  )
  .subscribe(() => {
    console.log("scroll-start");
  });

Вот кодовая ручка со сравнением всех трех: https://codepen.io/luckylooke/pen/zYvEoyd?editors=0010

0 голосов
/ 27 апреля 2020

Хотя это решение выглядит несколько сложным, оно достигает описанного вами поведения и может быть аккуратно заключено в пользовательский оператор.

import { of, merge, NEVER } from 'rxjs';
import { share, exhaustMap, debounceTime, takeUntil } from 'rxjs/operators';

const firstAfterInactiveFor = (ms) => (source) => {
  // Multicast the source since we need to subscribe to it twice.
  const sharedSource = source.pipe(share());

  return sharedSource.pipe(
    // Ignore source until we finish the observable returned from exhaustMap's
    // callback
    exhaustMap((firstEvent) =>
      // Create an observable that emits only the initial scroll event, but never
      // completes (on its own)
      merge(of(firstEvent), NEVER).pipe(
        // Complete the never-ending observable once the source is dormant for
        // the specified duration. Once this happens, the next source event
        // will be allowed through and the process will repeat.
        takeUntil(sharedSource.pipe(debounceTime(ms)))
      )
    )
  );
};

// This achieves the desired behavior.
stream.pipe(firstAfterInactiveFor(500))

...