简体   繁体   English

Rx.Observable.fromEvent(document,'click')与 document.addEventListener('click',回调)

[英]Rx.Observable.fromEvent(document, 'click') Vs. document.addEventListener('click', callback)

I just start learning reactive programming & using RxJS library. 我刚刚开始学习反应式编程并使用RxJS库。

One thing that is making my head turning is why would i use Rx while there the notion of events in JavaScript. 让我转头的一件事是,为什么我会在JavaScript中使用事件概念的同时使用Rx。

For example, What is the diff between Rx.Observable.fromEvent(document, 'click') and document.addEventListener('click', callback) . 例如, Rx.Observable.fromEvent(document, 'click')document.addEventListener('click', callback)之间的区别是什么。 Both are handling click events asynchronously. 两者都是异步处理click事件。

So why would I use observables in this case? 那为什么在这种情况下为什么要使用可观察物呢?

Because you can easily modify, combine observables where you would end up in kind of a callback hell with the default event listener. 因为您可以轻松进行修改,所以将可观察到的对象与默认事件侦听器结合在一起,最终会以某种回调地狱的形式出现。

Let's say, you want to listen to drag - events (all mouse-move events while having mouse clicked) 假设您要收听拖动事件-事件(单击鼠标时发生的所有鼠标移动事件)

let mouseDown = false;
document.addEventListener('mousedown', (ev) => mouseDown = true);
document.addEventListener('mouseup', (ev) => mouseDown = false);
document.addEventListener('mousemove', (ev) => {
   if(mouseDown) {
      // do something with it
   }
}

You already have to use some state to manage this, but it's not that bad. 您已经必须使用某种状态来管理它,但这还不错。 So now extend that to get the distance of the drag. 因此,现在将其扩展以获得拖动的距离。

let mouseDown = false;
let startPoint;
document.addEventListener('mousedown', (ev) => { 
   mouseDown = true;
   startpoint = ev.clientX
});

document.addEventListener('mouseup', (ev) => mouseDown = false);
document.addEventListener('mousemove', (ev) => {
   if(mouseDown) {
      let distance = ev.clientX - startPoint;
      // do something with it
   }
}

So another state variable and you can see that callbacks are taking over. 因此,另一个状态变量可以看到回调正在接管。 And this is quite a simple example. 这是一个非常简单的例子。 Here is the rxjs - way 这是rxjs-方法

let down$ = fromEvent(document, 'mousedown')
let up$ = fromEvent(document, 'mouseup')
let move$ = fromEvent(document, 'mousemove')

let drag$ = down$.pipe(
  switchMap(start => move$.pipe(
                        map(move => move.clientX - start.clientX),
                        takeUntil(up$)
                     )
            )
  )

There is no state evolved, all parts are reusable and it looks quite easy. 没有状态发展,所有部分都是可重用的,而且看起来很容易。 Now imagine adding touch support. 现在想象添加触摸支持。 With rxjs it's just merging the touchevents with their respective mouseevents and the other things are staying the same. 使用rxjs,它只是将touchevents与它们各自的mouseevents合并在一起,其他情况保持不变。 With plain events you would spend probably 30 lines or so on that 如果发生普通事件,您可能要花费30行左右

Basically, both give you a similar outcome with a slight different. 基本上,两者都会为您带来相似的结果,但有所不同。 Rx.Observable.fromEvent(document, 'click') is an observable. Rx.Observable.fromEvent(document, 'click')是可观察的。 That mean, you can subscribe and unsubscribe anytime and you have a list of operators to play with. 这意味着,您可以随时订阅和取消订阅,并且您可以使用一系列的运营商。 While document.addEventListener('click', callback) is to the callback. document.addEventListener('click', callback)位于回调中。

Take for example, you want to debounce the user click by 3 seconds and only want to listen to the click for 4 times only. 例如,您想在3秒内消除用户的点击,而只想听4次该点击。 With RxJs, you can do this pretty easy. 使用RxJ,您可以轻松完成此操作。

Rx.Observable.fromEvent(document, 'click')
  .debounce(3000)
  .take(4)
  .subscribe(ev => { 
    // do whatever you want to do.
  });

The same functionality might be achievable with listener and callback, but probably not this easy. 侦听器和回调可以实现相同的功能,但可能并非如此简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM