How to transfer html dom event through clojurescript channel - events

I am working on integrating the event system with om-event-bus, it use async/chan to transfer the events. However, it turns out html DOM event failed to be transfer through clojurescript's async channel. The properties in the transferred event becomes null and the internal functions are missing.
Define a channel first:
(def event-bus (chan))
Setup a dom node and attach a callback function to the keydown event. In the function, add the put the dom event in the channel (PS:I use om as UI)
(dom/section #js {:id "VRE"
:tabIndex 0
:onKeyDown #(put! event-bus %)))
wait to receive the event transferred
(go-loop
[]
(let [e (<! event-bus)]
(when e
(println "go-loop received" (.stringify js/JSON e))
(recur))))
When I type some key, the console will print:
go-loop received {"dispatchConfig":null,
"dispatchMarker":null,
"nativeEvent":null,
"type":null,
...
"_dispatchListeners":null,"_dispatchIDs":null}
All the properties are null and the internal functions like preventDefault are missing.
I guess there must be something I haven't understood. Does anyone have some ideas for fixing it? It would be great if you could give some hints/tips or other thoughts on the problem

You are trying to stringify an Event Object. This is not a good idea, look at this answer:
How to stringify event object?
Try extracting the interesting information (i.e which key was pressed) and passing that as a value to the channel.
To pass the whole Event Object and manipulating it on the receiving end might not be possible. I'm speculating but it seems like the Event Object is deleted before it is extracted from the channel.

Related

Using Observables to process queue messages which require a callback at end of processing?

This is a bit of a conceptual question, so let me know if it's off topic.
I'm looking at writing yet another library to process messages off a queue - in this case an Azure storage queue. It's pretty easy to create an observable and throw a message into it every time a message is available.
However, there's a snag here that I'm not sure how to handle. The issue is this: when you're done processing the message, you need to call an API on the storage queue to actually delete the message. Otherwise the visibility timeout will expire and the message will reappear to be dequeued again.
As an example, here's how this loop looks in C#:
public event EventHandler<string> OnMessage;
public void Run()
{
while(true)
{
// Read message
var message = queue.GetMessage();
if (message != null)
{
// Run any handlers
OnMessage?.Invoke(this, message.AsString);
// Delete off queue when done
queue.DeleteMessage(message);
}
else
{
Thread.Sleep(2500);
}
}
}
The important thing here is that we read the message, trigger any registered event handlers to do things, then delete the message after the handlers are done. I've omitted error handling here, but in general if the handler fails we should NOT delete the message, but instead let it return to visibility automatically and get redelivered later.
How do you handle this kind of thing using Rx? Ideally I'd like to expose the observable for anyone to subscribe to. But I need to do stuff at the end of processing for that message, whatever the "end" happens to mean here.
I can think of a couple of possible solutions, but I don't really like any of them. One would be to have the library call a function supplied by the consumer, that takes in the source observable, hooks up whatever it wants, then returns a new observable that the library can then subscribe on to do the final cleanup. But that's pretty limiting, as consumers basically only have one shot to hook up to the messages, which seems pretty limiting.
I guess I could put the call to delete the message after the call to onNext, but then I don't know if the processing succeeded or failed unless there's some sort of back channel in that api I don't know about?
Any ideas/suggestions/previous experience here?
Try having a play with this:
IObservable<int> source =
Observable
.Range(0, 3)
.Select(x =>
Observable
.Using(
() => Disposable.Create(() => Console.WriteLine($"Removing {x}")),
d => Observable.Return(x)))
.Merge();
source
.Subscribe(x => Console.WriteLine($"Processing {x}"));
It produces:
Processing 0
Removing 0
Processing 1
Removing 1
Processing 2
Removing 2

Trigger/Handle events between programs in different ABAP sessions

I have two programs running in separated sessions. I want to send a event from program A and catch this event in program B.
How can I do that ?
Using class-based events is not really an option, as these cannot be used to communicate between user sessions.
There is a mechanism that you can use to send messages between sessions: ABAP Messaging Channels. You can send anything that is either a text string, a byte string or can be serialised in any of the above.
You will need to create such a message channel using the repository browser SE80 (Create > Connectivity > ABAP Messaging Channel) or with the Eclipse ADT (New > ABAP Messaging Channel Application).
In there, you will have to define:
The message type (text vs binary)
The ABAP programs that are authorised to access the message channel.
The scope of the messages (i.e. do you want to send messages between users? or just for the same user? what about between application servers?)
The message channels work through a publish - subscribe mechanism. You will have to use specialised classes to publish to the channel (inside report A) and to read from the channel (inside report B). In order to wait for a message to arrive once you have subscribed, you can use the statement WAIT FOR MESSAGE CHANNELS.
Example code:
" publishing a message
CAST if_amc_message_producer_text(
cl_amc_channel_manager=>create_message_producer(
i_application_id = 'DEMO_AMC'
i_channel_id = '/demo_text'
i_suppress_echo = abap_true )
)->send( i_message = text_message ).
" subscribing to a channel
DATA(lo_receiver) = NEW message_receiver( ).
cl_amc_channel_manager=>create_message_consumer(
i_application_id = 'DEMO_AMC'
i_channel_id = '/demo_text'
)->start_message_delivery( i_receiver = lo_receiver )
" waiting for a message
WAIT FOR MESSAGING CHANNELS
UNTIL lo_receiver->text_message IS NOT INITIAL
UP TO time SECONDS.
If you want to avoid waiting inside your subscriber report B and to do something else in the meanwhile, then you can wrap the WAIT FOR... statement inside a RFC and call this RFC using the aRFC variant. This would allow you to continue doing stuff inside report B while waiting for an event to happen. When this event happens, the aRFC callback method that you defined inside your report when calling the RFC would be executed.
Inside the RFC, you would simply have the subscription part and the WAIT statement plus an assignment of the message itself to an EXPORTING parameter. In your report, you could have something like:
CALL FUNCTION 'ZMY_AMC_WRAPPER' STARTING NEW TASK 'MY_TASK'
CALLING lo_listener->my_method ON END OF TASK.
" inside your 'listener' class implementation
METHOD my_method.
DATA lv_message TYPE my_message_type.
RECEIVE RESULTS FROM FUNCTION 'ZMY_AMC_WRAPPER'
IMPORTING ev_message = lv_message.
" do something with the lv_message
ENDMETHOD.
You could emulate it by checking in program B if a parameter in SAP memory has changed. program A will set this parameter to send the event. (ie SET/ GET PARAMETER ...). In effect you're polling event in B.
There a a lot of unknown in your desription. For example is the event a one-shot operation or can A send several event ? if so B will have to clear the parameter when done treating the event so that A know it's OK to send a new one (and A will have to wait for the parameter to clear after having set it)...
edited : removed the part about having no messaging in ABAP, since Seban shown i was wrong

Why does Rxjs unsubscribe on error?

In short:
How to proceed listening after an error in stream without putting a .catch before every .subscribe?
If you need more details they are here:
Lets assume I have a Subject of current user or null. I get the data from API sometimes and send to the Subject. It updates the view accordingly.
But at some point error occurs on my server and I want my application to continue working as before but notify some places about the error and KEEP listening to my Subject.
Initially I thought that if I just do userSubject.error(...) it will only trigger .catch callback and error handlers on subscribes and skip all success handlers and chains.
And if after I call userSubject.next(...) all my chains and subscribers will work as before
BUT unluckily it is not the case. After the first uncaught .error it unsubscribes subscribers from the stream and they do not operate any more.
So my question: Why???
And what to do instead if I want to handle null value normally but also handle errors only in some places?
Here is the link to RxJs source code where Subscriber unsubscribes on error
https://github.com/ReactiveX/rxjs/blob/master/src/Subscriber.ts#L140
Rx observables follow the grammar next*(error|complete)?, meaning that they can produce nothing after error or complete notification has been delivered.
An explanation of why this matters can be found from Rx design guidelines:
The single message indicating that an observable sequence has finished ensures that consumers of the observable sequence can deterministically establish that it is safe to perform cleanup operations.
A single failure further ensures that abort semantics can be maintained for operators that work on multiple observable sequences.
In short, if you want your observers to keep listening to the subject after a server error has occurred, do not deliver that error to the subject, but rather handle it in some other way (e.g. use catch, retry or deliver the error to a dedicated subject).
Every Observable emits zero or more next notifications and one error or complete but never both.
For this reason, Subjects have internal state.
Then it depends how you construct your chain. For example you can use retry() to resubscribe to its source Observable on error.
Or when you pass values to your Subject you can send only next notifications and ignore the other two:
.subscribe(v => subject.next(v));
Or if you want to throw error when the user is null you can use any operator that captures exceptions and sends them as error notifications. For example like this:
.map(v => {
if (v === null) {
throw new Error("It's broken");
}
return v;
})
Anyway it's hard to give more precise advice without any code.

Observing when stream is unsubscribed

I have an RxJS observable stream that I'm sharing like the following:
var sub = Observable.create(obs => {
// logic here
return () => {
// call rest service to notify server
};
})
.publish()
.refCount();
When the last subscriber unsubscribes, I need to make a REST request. The obvious choice is to add that call into the return cleanup function - but you then have broken out of any observable sequence and any errors etc aren't easily handled.
I could just use a Subject, push a value onto it in the cleanup function, and observe it elsewhere with the REST call hanging off that.
Ideally I'd do something like concatenating to the disposed stream with my REST call (concat obviously wouldn't work as it's not completing).
Does anyone have any suggestions for the cleanest way of handling this? All the options above seem a bit clunky and I feel like I've missed something.
You could implement a finally(...) in your stream, that does the cleanup.
The finally is automatically executed when the stream finalizes (error or complete).
Note: This will not work when you unsubscribe manually and not call complete on your stream.

Difference between dispatch and emit in Flux/React Native

I'm new in Flux/React Native.
I'm quite confused about dispatch vs emit using in Flux.
What is the main difference between them? And what happen when I use same Action Type in dispatch and emit.
For example:
Dispatcher.dispatch({
actionType: 'ACTION1'
});
SomeStore.emit('ACTION1');
In Flux, events are emitted by the store indicating a change in its state. This 'change' event is listened to by views. This will prompt a view to fetch new state from the store. Mind you, the event never contains payload / information about the new state. It is really just what it reads - an event.
Actions are slightly different. While they are indeed events, they are things that occur in our domain eg., Add item to cart. And they carry a payload that contains information about the action, eg.,
{
id: ‘add-item-to-cart’,
payload: {
cartId: 123,
itemId: 1234,
name: ‘Box of chocolates’,
quantity: 1
}
}
Actions are 'dispatched' from the views and the store(s) responds to the dispatch by possibly changing its state and emitting a 'change' event.
So basically:
A view dispatches an action with a payload (usually due to a user interaction) via the dispatcher
The store (which had previously registered itself with the dispatcher)
is notified of the action and uses the payload to change its state and emit an event.
The view (which had previously registered itself with the store) is notified of the change event which causes it to get the new state from the store and change itself.
So that's the difference. And about the question "use same Action Type in dispatch and emit", it doesn't really make sense, does it?
I suggest you read this blog post - http://blog.andrewray.me/flux-for-stupid-people/ (The title means no offence BTW :))
You already know this, but I'll say it again: A unidirectional data flow is central to the Flux pattern. That means data (not control) always flows in one direction.

Resources