简体   繁体   中英

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

I just start learning reactive programming & using RxJS library.

One thing that is making my head turning is why would i use Rx while there the notion of events in JavaScript.

For example, What is the diff between Rx.Observable.fromEvent(document, 'click') and document.addEventListener('click', callback) . Both are handling click events asynchronously.

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

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. With plain events you would spend probably 30 lines or so on that

Basically, both give you a similar outcome with a slight different. Rx.Observable.fromEvent(document, 'click') is an observable. 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.

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. With RxJs, you can do this pretty easy.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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