I have a hot observable that emits messages. Currently I'm using publishReplay(1).refCount() so everyone subscribing will receive the last message. Now, the messages passing through May have a field containing a boolean to determine if it should be just passed through to all subscribers, or if it should be stored in the replay to be emitted to all new sebscribers too.
Has anyone any idea, how to achieve this usecase?
I implemented my own publishReplayConditionally and ConditionalReplaySubject. They additionally accept an expression as a parameter to decide if the value should be stored.
Related
I'm having a trouble wrapping my head around following concept.
I'm sending OSC messages to query status of instruments in Ableton, so I have emmiter/receiver combo going on. Now, thing is that I'd like to avoid having to keep up some sort of global state and wrap everything around this.
and I do communicate with Ableto in following fashion:
sender.emit("/live/device", queryData);
receiver.on("/live/device", function(responseData){
// process response here...
})
So you can tell that I'm not really sure when I got data back and cannot really sequence new queries based on responses.
What I'd like to do is to simply
query number of instruments on ONE certain channel
get number back
query parameters of each instrument of that channel based on first query
receive parameters back
But problem is that I have no idea how to wrap eventListeners to respond to these queries, or rather how to sequence them in way that is non-blocking and yet still avoiding having some sort of global state going on.
Querying data and storing Promises to be resolved by eventListener seems like a solution, but then I'm stuck on how to pass them back to sequence.
After some research, it seems that this kind of behaving breaks the whole concept of event listeners, but then I suppose the whole point is to have some global state to keep track of what is going on, right?
Event listeners are telling you some asynchronous action coming from a user action or any other interrupt. Depending on the API you are facing, they might have re-used event listeners for replies instead of providing a promise or callback return for the send API. If the server has multiple clients interacting with it, it might want to tell all clients at the same time when their state changes as well.
If you are sure there is no way to directly provide a callback in the send method for a reply to your request or a request does not yield a promise that resolves with the reply at some point, there are usually workarounds.
Option 1: Send context, receive it back
There are APIs that allow sending a "context" object or string to the API. The API then sends this context to the event listeners whenever it answers this specific question along with their payload. This way, the context part of their payload can be checked if it's the answer to the request. You could write your own little wrapper functions for a more direct send/reply pattern then.
Option 2: Figure out the result data, if it fits your request
If the resulting data has something specific to match on, like keys on a JSON object, it may be possible to find out what the request was.
Option 3: Use state on your side to keep track of everything
In most cases where I have seen such APIs, the server didn't care much about requests and only sent out their current state if it was changed by some kind of request. The client needs to replicate the state of the server by listening to all events, if it wants to show the current server state.
In most situations where I faced this issue, I thought about Option 1 or 2 but ended up with Option 3 anyways: Other clients or hardware switches might interfere with my client UI and change the server state without me listening on that change. That way I would loose information that invalidates my UI, so I would need to listen and replicate the state of the server/machine/hardware anyways.
I just completed a React component. It calls a service in an action, and puts the result into the state in a reducer. Then the React mechanism updates the component, and then the dom.
When I finished the component, it was checking that it was getting the values it was expecting from the service. After several rounds of pull requests and comments, there is no particular data in the component. The data received from the service is just kept as “data”, and it is passed to whoever needs it without examination or alteration. Even when I pass the data to the subcomponent, I pass the whole data object using a JSX spread, and it takes the pieces it needs.
I am very uncomfortable programming this way. If the service returns unexpected data, all I will be able to tell the business is “it broke.” If the server is supposed to send person.arm.hand, and it sends person without an arm property, the program will throw an exception when it tries to dereference person.arm.hand.
I am told that I should rely on the integration tests. Checks for expected values shouldn’t be put into the code.
Is that standard industry practice?
Something I noticed the other day. I was subscribing to the Actions stream inside #ngrx/effects. I noticed (an issue for me) where a component, which subscribes to Actions late, receives the last dispatched action. This I can see is because the dispatcher inside #ngrx/store is a BehaviourSubject and quoting the RxJS docs:
Rx.BehaviorSubject class
Represents a value that changes over time. Observers can subscribe to the subject to receive the last (or initial) value and all subsequent notifications.
Unfortunately, I'd like to subscribe to the actions stream without retrieving the last value. It creates problems for me like showing error messages when a user returns to a page.
The difference between BehaviorSubject and Subject (which does it the way I'd like) is demo'd here:
https://codepen.io/anon/pen/zwgype
Is there any way of achieving this?
You can skip the first value with the 'skip' operator:
someBehaviorSubject.skip(1)
Is there a way to know if an Rx.Observable has completed AFTER the fact, i.e. after onCompleted call on the subscribers? This would be similar to the has_next method for iterators. I could not find anything in the doc (or elsewhere) on that subject.
For a cold observable, the question would not make so much sense, as one can resubscribe at will, and the observable will be started anew. For a time-limited hot observable, one could imagine the edge case of being passed a reference to that hot observable, and subscribing for its values, never receiving anything and not even knowing that nothing will ever be received.
Evers obserbable or observer have the property isStopped. This is eighter true if it is completed or error was thrown or it is false which means it it still active.
Here is the answer I got from another channel (quoted below).
The "usual" channels of creating a hot observable, such as creating a subject or using .publish() will "replay" the terminal message (i.e., onError or onCompleted), but there is no such guarantee in general. I would argue though that any hot sequence that did not have this terminal message replay violates the contract of an observable, and appropriate bugs should be filed.
I'm working on a couple sites that share some Socket.io initialization code. Also shared is a global var. If this var has a value I need to send it over in all socket emits.
I have not been able to figure out a good way to append this variable to all outgoing emits. I was hoping that Socket.io would have a method that is called whenever an emit is fired (just before sending the data), allowing you to add to the data as needed. But, if it exists, I could not find it.
Any suggestions?
It's ugly, but you could save the existing, and write your own emit function that does what you want, and then calls the original emit.