Re: [whatwg/dom] Improving ergonomics of events with Observable (#544)

@othermaciej Glad you found it helpful.  As neither a browser implementer nor a champion, I'm trying to leave this conversation to people more-qualified-than-me to have it, but I'll also try to help where I can.

## Observables operators and the event loop

If I'm understanding your second question correctly, you're asking if `takeUntil` needs to wait for a turn around the event loop?  No, subscription is synchronous.  Here's a [simplified implementation of Observable](https://github.com/material-motion/indefinite-observable-js/blob/develop/src/IndefiniteObservable.ts) (without the `error` and `complete` channels, and without `AbortController`).

As you can see, `subscribe` just passes its argument to the function that was provided to the constructor.  It's all synchronous, so there shouldn't be any additional passes through the event loop.

## Promise-returning operators and the event loop

I'm unfamiliar with the promise-returning functions, so I'll let @benlesh and @domenic speak to them.

## Is this really useful?

As for your last question, yes, many of us do find value in this style of programming (as you can see by how many positive reactions have appeared on Ben's proposal just today).  I'm afraid that this can very easily turn into a tangent on the value of reactive programming, and I'm not sure if this is the appropriate venue for that conversation, so I'll try to be brief.

I find that reactive programming is more **modular**, **testable**, **composable**, and **maintainable** than the same logic expressed imperatively.  One property of reactive programming is that the data flow through the system is immutably defined at definition time.  This makes it easier to reason about as the application becomes more complex (hence, better maintainability).  For example:

```ts
const movePoint$ = element.on('mousemove').map(
  ({ pageX, pageY }) => ({ x: pageX, y: pageY })
);
```
will always represent the mouse's last known location in `element`.  Any code that depends on `movePoint$` can trust that no other code can change that.  Moreover, any code that takes a stream of points can consume `movePoint$` without needing to know anything about `mousemove`.

As a more concrete example, suppose that you had an application that understood `PointerEvent` and you wanted to add support for `TouchEvent`.  Here's how you might do that with Observables:

```typescript
function convertTouchEventsToPointerEvents(touchEvent$) {
  return touchEvent$.map(
    ({ type, targetTouches, changedTouches }) => Array.from(
      ['touchend', 'touchcancel'].includes(type)
        ? changedTouches
        : targetTouches,
      ({ pageX, pageY, identifier }) => (
        {
          pageX,
          pageY,
          pointerId: identifier,
          type: TOUCH_TYPE_TO_POINTER_TYPE[type]
        }
      )
    )
  }).flatten();
}

function getPointerEventStreamsFromElement(element) {
  if (typeof PointerEvent !== 'undefined') {
    return {
      down$: element.on('pointerdown'),
      move$: element.on('pointermove'),
      up$: element.on('pointerup'),
      cancel$: element.on('pointercancel'),
    };
  } else {
    return {
      down$: element.on('mousedown').merge(
        convertTouchEventsToPointerEvents(element.on('touchstart'))
      ),
      move$: element.on('mousemove').merge(
        convertTouchEventsToPointerEvents(element.on('touchmove', element))
      ),
      up$: element.on('mouseup').merge(
        convertTouchEventsToPointerEvents(element.on('touchend')
      ),
      cancel$: convertTouchEventsToPointerEvents(element.on('touchcancel')),
    };
  }
}
```
That's code pulled from our codebase.  The ability to add support for `TouchEvent` to our entire library with just the two functions above demonstrates the power of reactive programming, of which observables are the cornerstone.  Unlocking that power in platform APIs like `EventTarget` is why folks are so excited to see this proposal.  

It might be hard to see a meaningful difference between the imperative and reactive styles in the simple examples included in the proposal, but the reactive model has many benefits when writing real applications.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/544#issuecomment-351626947

Received on Thursday, 14 December 2017 07:08:47 UTC