takeUntil не удалось предотвратить выбросы от наблюдаемых - PullRequest
0 голосов
/ 01 апреля 2019

Я пытаюсь создать свои собственные события щелчка, удержания и перетаскивания, используя Rxjs и события mousedown, mouseup и mousemove.Мои попытки используют несколько потоков, которые начинаются с события mousedown, каждый с takeUntil, который прослушивает выбросы из других потоков.По сути, как только один из потоков «заявил» о действии (то есть прошел все требования и выдал значение), другие наблюдаемые должны завершиться без выбросов.

Я посмотрел на другие ответы и подумал, что это может что-то иметьделать с таймером, работающим асинхронно, но это происходит между потоками, которые не используют таймер, например, перетаскиваниеЯ играл в кодахandbox.io, используя rxjs v6.

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

Код показан ниже:

const mouse_Down$ = fromEvent(document, "mousedown").pipe(
  tap(event => event.preventDefault())
);

const mouse_Up$ = fromEvent(document, "mouseup").pipe(
  tap(event => event.preventDefault())
);

const mouse_Move$ = fromEvent(document, "mousemove");

const mouse_drag$ = mouse_Down$
  .pipe(
    mergeMap(mouseDownEvent =>
      mouse_Move$.pipe(takeUntil(merge(mouse_Up$, mouse_Hold$, mouse_drag$)))
    )
  ).subscribe(event => console.log("Drag"));

const mouse_Hold$ = mouse_Down$
  .pipe(
    mergeMap(mouseDownEvent =>
      timer(1000).pipe(takeUntil(merge(mouse_drag$, mouse_Click$)))
    )
  ).subscribe(event => console.log("Hold"));

const mouse_Click$ = mouse_Down$
  .pipe(
    mergeMap(mouseDownEvent =>
      mouse_Up$.pipe(takeUntil(mouse_drag$, mouse_Hold$))
    )
  ).subscribe(event => console.log("Click"));

Ожидаемое поведение: Если пользователь перемещает мышь в течение 1 с после события mousedown, поток mouse_drag$ должен начать излучаться, а внутренняя наблюдаемая mouse_Click$/mouse_Hold$ должна завершиться (благодаря takeUntil(mouse_drag$) безиспускание и ожидание следующей эмиссии mouse_down$.

Если кнопка мыши остается нажатой в течение более 1 с без движения, mouse_Hold$ должен испустить и внутренняя наблюдаемая mouse_drag$/mouse_click$ должна завершиться (благодаря takeUntil(mouse_Hold$) без излучения и ожидайте следующего mouse_down$ излучения.

Фактическое поведение: В настоящее время mouse_Drag$ будет излучать, mouse_Hold$ будет излучать через одну секунду, а mouse_Click$ будетemit, когда кнопка отпущена.

Мой вопрос: почему из-за излучающего потока mouse_Drag$ внутренняя наблюдаемая mouse_Hold$ и mouse_Click$ не завершается без излучения?

Ответы [ 2 ]

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

уточнить:

  1. которую вы хотите испустить из mouse_Hold $, если мышь удерживается более 1 секунды.
  2. Вы хотите получить значения из mouse_drag $, если МЕНЬШЕ, то через 1 секунду после выпадающего списка мыши и mouseMove.

Вам не нужно ничего завершать, иначе все поведение будет работать только один раз. Итак, план: 3. mouse_drag $ - Если mousedown - проверьте mouseMove на 1 секунду. Если mouseMove испускает - переключиться на значения mouseMove 4. mouse_Hold $ - если mouseDown - проверить mouseMove на 1 секунду. Если mouseMove не излучает - переключитесь на mouseHold и сделайте так, чтобы он излучал «Hold»

let Rx = window['rxjs'];
const {defer, of, timer, fromEvent, merge, race} = Rx;
const {switchMap, repeat, tap, takeUntil, filter} = Rx.operators;
const {ajax} = Rx.ajax;
console.clear();

const mouse_Down$ = fromEvent(document, "mousedown");

const mouse_Up$ = fromEvent(document, "mouseup");

const mouse_Move$ = fromEvent(document, "mousemove");

const timer$ = timer(2000);

mouse_Hold$ = mouse_Down$.pipe(
  switchMap((downEvent) => {
    return timer$.pipe(
      switchMap((time) => of('HOLD'))
    );
  }),
  takeUntil(merge(mouse_Up$, mouse_Move$)),
  repeat(mouse_Down$)
)

mouse_Hold$.subscribe(console.warn);

mouse_drags$ = mouse_Down$.pipe(
  switchMap(() => mouse_Move$),
    takeUntil(mouse_Up$, $mouse_Hold),
  repeat(mouse_Down$)
)

mouse_drags$.subscribe(console.log);

Вот кодекс: https://codepen.io/kievsash/pen/oOmMwp?editors=0010

0 голосов
/ 01 апреля 2019

Тейк до должен быть в конце вашей цепочки

Это отменит всю цепочку.

const { fromEvent } = rxjs;
const { tap, takeUntil, mergeMap, merge } = rxjs.operators;

const mouse_Down$ = fromEvent(document, "mousedown").pipe(
  tap(event => event.preventDefault())
);

const mouse_Up$ = fromEvent(document, "mouseup").pipe(
  tap(event => event.preventDefault())
);

const mouse_Move$ = fromEvent(document, "mousemove");

const mouse_drag$ = mouse_Down$
  .pipe(
    mergeMap(mouseDownEvent =>
      mouse_Move$
    ),
    takeUntil(mouse_Up$)
  ).subscribe(event => console.log("Drag"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
...