takeUntil未能防止可观察到的排放

时间:2019-04-01 00:35:54

标签: rxjs rxjs-pipeable-operators

我正在尝试使用Rxjs以及mousedown,mouseup和mousemove事件创建自己的单击,按住和拖动事件。我的尝试使用了许多从mousedown事件开始的流,每个流都带有一个takeUntil来侦听其他流的排放。基本上,一旦其中一个流“声明”了该动作(即通过了所有要求并发出了值),其他可观察对象就应该完成而不会产生任何排放。

我看了其他答案,认为可能与计时器异步运行有关,但它发生在不依赖计时器的流之间,例如拖动并单击。我一直在使用rxjs v6在codesandbox.io中玩耍。

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

预期行为: 如果用户在mousedown事件的1s内移动鼠标,mouse_drag$流应开始发出,mouse_Click$/mouse_Hold$的内部可观察对象应完成(由于takeUntil(mouse_drag$)而没有发出,等待下一个mouse_down$发射。

如果在不移动mouse_Hold$的情况下按住鼠标键超过1秒钟,并且mouse_drag$/mouse_click$的内部可观察对象应该完成(由于takeUntil(mouse_Hold$)而没有发出,等待下一个mouse_down$发射。

实际行为::当前mouse_Drag$将发出,mouse_Hold$将在一秒钟后发出,mouse_Click$将在释放按钮时发出。

我的问题是,为什么发射mouse_Drag$的流不会导致mouse_Hold$mouse_Click$的内部观察完成而不发射?

2 个答案:

答案 0 :(得分:0)

收紧直到需要在链的尽头

这将取消整个链条。

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>

答案 1 :(得分:0)

要澄清:

  1. 如果要按住鼠标1秒钟以上,则要从mouse_Hold $中发出信号。
  2. 如果要从mouse_drag $中获取值,请在鼠标下拉和mouseMove之后再过1秒,然后再单击LESS。

您无需完成任何操作,因为否则所有行为将仅起作用一次。 所以计划:  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);

这是一个codepen:https://codepen.io/kievsash/pen/oOmMwp?editors=0010