2

I'm trying to understand how Observables and RxJS works, so this might be not at all the point of how to use them.

I have an Angular2 application and am additionally using RxJS Observables to send events around. Now for a special type of error events, I'd like to know if the event has already been handled by another Subscriber. Multiple Subscribers might exist on the Observable and some might take full responsibility of the event so that others won't get it anymore.

The idea comes from how Routed Events work in WPF. In the event handler you get the RoutedEventArgs parameter, which has a Property Handled:

If setting, set to true if the event is to be marked handled; otherwise false. If reading this value, true indicates that either a class handler, or some instance handler along the route, has already marked this event handled. false.indicates that no such handler has marked the event handled.

Another implementation example would be how the middleware works in the ASP.NET Core Pipeline - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware - You can either call the next middleware or just return a result.

I was thinking about adding the Handled property to the event I'd throw into the observable pipe, but I'm not sure if it's the idiomatic way of doing this in RxJS.

Mark van Straten
  • 9,287
  • 3
  • 38
  • 57
peter
  • 14,348
  • 9
  • 62
  • 96

1 Answers1

1

Typically the way you do this with observables is you don't hand the observable to everyone and everyone subscribes to it. Instead you give each interested party a chance to "add to the pipeline" and then finally subscribe once. There are many ways to do this. The easiest is to not actually give anyone the observable. But instead let them provide you with callbacks:

class Foo {

   observable = ...;
   callbacks = [];

   addCallback(callback) { this.callbacks.push(callback); }

   constructor() {

       // subscribe to the observable and call any registered callbacks
       this.observable.subscribe(e => {
           for (const cb of this.callbacks) {
               // callback returns true if it has "handled" the event
               if (cb(e)) {
                   return; // do not call any other callbacks
               }
           }
       });
   }
}

const foo = new Foo();

// subscriber1 handles "type1" events
foo.addCallback(ev => ev.type === "type1");

// subscriber2
foo.addCallback(ev => ev.type === "type2");

This is the simplest way. There are other ways where Foo exposes observables for each client and monitors their results to build the pipeline.

Brandon
  • 38,310
  • 8
  • 82
  • 87
  • Isn't this semantically the same as implementing `Subscribable`? If so it might be more composable and easier to consume if that we're done directly. – Aluan Haddad Mar 07 '17 at 17:12
  • @AluanHaddad no it is semantically different otherwise the OP wouldn't be asking the question. With RxJS observables data flows one way: from observable source to subscribers. The only information that flows from subscribers back to observable sources is the subscribe/unsubscribe calls. This question is about how to have subscribers communicate back upstream that no other subscribers should see a value. – Brandon Mar 07 '17 at 17:15
  • Right but Observable is subscribed to via its implementation of Subscribable. Also the OP only says he wants to know if an event has been handled not to communicate this fact externally. I'm honestly curious though because I don't know what constitutes of valid subscribable. In other words is allowed to filter itself like this? I would think so. – Aluan Haddad Mar 07 '17 at 17:19
  • 1
    OP is implicitly communicating this "handled" fact externally because subsequent subscribers will either not get the event or will have knowledge that it has already been handled. Subscribables *are* filterable. But I don't believe their filters are based upon synchronous return values from their subscribers (at least not Subscribables in the context of Rx). In Rx, Subscribables are decoupled from their Subscribers outside of the subscribe/unsubscribe requests. – Brandon Mar 07 '17 at 19:30
  • Thank you for taking the time to answer . That's exactly exactly what I was asking about. – Aluan Haddad Mar 07 '17 at 19:31
  • Ok, thx - so modifying the object passed on to observable is a terrible idea, and Rx doesn't have anything out of the box, so simple event handlers will have to do it, thx. – peter Mar 09 '17 at 10:44