0MQ req wait for rep in Node.js - javascript

I'm new to javascript, Node.js, and 0MQ, so n00b * 3 here.
I want to set up a simple request and reply, but I want the client to wait for a response before sending out the next request.
The zguide goes over this, but the Node.js version does not behave like the C version (which is what I want).
I realize I'm butting up against a paradigm shift here in how I look at the problem, but I still feel like I should be able to do this. Can I make a recv call (or something similar) in the client?

You're right, the node.js version of ZMQ doesn't behave the way you would expect it to if you're coming from the C version, but it actually is behaving according to the rules, it's just adding in a bit of its own sauce to the mix.
Specifically, the C bindings will throw an error if you try to break the strict REQ/REP/REQ/REP cycle. In node.js, it will cache the out-of-order message until the previous response comes back, and then send out that new message... so you're still getting REQ/REP/REQ/REP, in order, and you can choose to send a message whenever you want without an error.
This is probably a poor design choice on the part of the node ZMQ binding authors, first of all because it's confusing to new users such as yourself, and second of all if you're using REQ/REP you'd probably prefer a hard failure if you go out of order, otherwise you'd be using a different socket type.

Related

Wait for response from emitted message?

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.

Refactoring websocket code that uses global variables into events / async programming

There's a bit of someone else's code I am trying to add functionality to. It's using websockets to communicate with a server which I will most likely not be able to change (the server runs on a 3$ micro-controller...)
The pattern used, for instance when uploading data to the server, consists in using global variables, then sending a series of messages on the socket, as well as having an 'onmessage' which will handle the response. This seems clumsy, given that it assumes that there is only ever one socket call made at a time (I think the server guarantees that in fact). The messages sent by the server can be multiple, and even figuring out when the messages are finished is fiddly.
I am thinking of making things so that I have a better handle on things, mostly w.r.t. being able to know when the response has arrived (and finished), going to patterns like
function save_file(name, data, callback) {
}
And perhaps at some point I can even turn them into async functions.
So couple of ideas:
- is there some kind of identifier that I could find in the websocket object that might allow me to better string together request and response?
- short of that, what is the right pattern? I started using custom events, that allows me to much better tie the whole process, where I can supply a callback by attaching it to the event, but even doing removeEventListener is tricky because I need to keep reference to every single listener to make sure I can remove them later.
Any advice anyone?

Prevent return until condition is met

I know these types of question come up fairly often, but I need help with a wait-like mechanism in JavaScript. I know setTimeout-based solutions are going to come up, but I'm not sure how to pull it off in my case.
I'm writing an API that uses a WebSocket internally. There's a connect() method that sets up the WebSocket, and I need to make it not return until after the WebSocket is set up. I'd like it to return a value for whether or not the connection was successful, but that's not the main problem.
The issue I'm hitting is that after a user calls connect(), they may call another method that relies on the WebSocket to be properly set up. If it's called too early, an error is thrown stating that the object is not usable.
My current solution is setting a "connected" flag when I've determined a successful connection and in each method checking for it in each method. If it's not connected, I add the method call to a queue that is ran through by the same code that sets the flag. This works, but it introduces that style of code all over my methods and also seems misleading from the user-perspective, since the call of those functions is deferred. Also, if there is other user code that relies on those calls being completed before it gets to them, it won't behave as expected.
I've been racking my brain with how to handle this case. The easiest solution is to just find a way to block returning from connect until after the WebSocket is set up, but that's not really the JavaScript way. The other option was to make them provide the rest of their code in a callback, but that seems like a weird thing to do in this case. Maybe I'm over-thinking it?
Edit: To better illustrate my problem, here's a example of what the user could do:
var client = new Client(options);
client.connect();
client.getServerStatus();
The getServerStatus() method would be using the WebSocket internally. If the WebSocket is not set up yet, the user will get that not usable error.
Todays Javascript does not really work like that unfortunately. In the future (ECMA6) there may be new language features that address this issue more directly. However for now you are stuck with the currently accepted method of handling asynchronous events, which is limited to callbacks. You may also want to explore 'promises' to handle 'callback hell' however you will need a library for this.
And yes it does seem strange to have callbacks everywhere, especially for someone new to web programming, however it is really the only way to go about it at this stage (assuming you want a cross-browser friendly solution).
"Wait" is almost the keyword you are looking for. Actually, it's yield that does this. See e.g. MDN's documentation.
There's a connect() method that sets up the WebSocket, and I need to make it not return until after the WebSocket is set up
That isn't going to happen unless you rewrite the javascript execution engine.
Either the code trying to send data will need to check the socket state (I'd go with encapsulating the socket in a object, supplying a method which sets a member variable on the open/close events and poll the state of that member variable from the external code). Alternatively you could add messages and call backs to a queue and process the queue when the socket connects.

How does NodeJS handle async file IO?

Having worked with NodeJS for some time now, I've been wondering about how node handles file operations internally.
Considering the following pseudo code:
initialize http server
on connection:
modify_some_file:
on success:
print "it worked"
Let's consider two users A & B that try to access the page nearly simultaneously. Let's further assume A is the first one to connect, then the following happens:
A connects
NodeJS initializes the file operation and tells the operating system to be notified once it is done
And here's what I'm wondering about: Let's say, the file operation isn't done yet and B connects, what does node do? How and when does it access the file when it is still in the process of "being modified"?
I hope my question is somewhat clear ;)
Looking forward to your answers!
AFAIK, Node won't care.
At least on Unix, it's perfectly legal to have multiple writers to the same file. Sometimes that's not a problem (say your file consists of fixed-size records, where writer #1 writes to record X and writer #2 writes to record Y, with X !== Y), and sometimes it is (same example: when both writers want to write to record X).
In Node, the problems are mitigated because I/O operations "take turns", but I think there's still potential of two writers getting in each others way. It's up to the programmer to make sure that doesn't happen.
With Node, you could use the *Sync() versions of the fs operations (but those will block your app during the operation), use append mode (which is only atomic up to certain write sizes I think, and it depends on your requirements if appending is actually useful), use some form of locking, or use something like a queue where write operations would be put onto the queue and there's a single queue consumer to handle the writes.

HTTP status codes - Backbone.js and Jquery

Backbone.js has a neat feature where you are able to sync changes back to your sever using standard HTTP verbs.
For example you may have a model object and some code which executes a get:
var coolModel = Backbone.Model.extend({url:'mysite/mymodel'});
var myCoolModel = new coolModel();
myCoolModel.fetch({error:processError});
Under the case where the server returns a 4XX or 5XX the error function 'processError' is run, which is great, you are able to process the error in which ever way suits.
As backbone.js uses jQuery to perform the GET, Jquery reports the error, which it is. The 4XX is a valid error which should be recovered from, my client side app is not broken, it just needs to behave slightly differently.
My question is - is it considered bad practice to have this error raised from jQuery displayed in the browsers console window or status bar? Should I be suppressing this error somehow so that users in production don't see an error reported by the browser when the error is recoverable? Or is it correct in the land of HTTP to leave it as is?
Handling errors in Backbone is a really interesting topic and one I hope to write about at some point. It's very nice to visually indicate errors to your users in a non-obtrusive manner. Some things to consider are:
Your users are not looking at the status bar or developer tools
Your users are expecting specific behavior from your application
When your application does not behave correctly visual problem indicators are important
I'd recommend considering how the failure impacts the user's intention. For instance if they are fetching data for the first page and that data is not returned correctly, you will need to handle the error by displaying a failure of data retrieved (or even better fall back on previously loaded data from a cache... it it exists). If the intention is to save an item and the error code returned is 400 that is definitely not a success and should be indicated that the user should retry saving again, (or perhaps attempt a re-save on an interval).
You can silently ignore errors and not indicate them, but your users will get confused and it will lead to unexpected problems. I can't preach to use perfect error handling, because I'm still getting better at it myself.
I would say HTTP status codes are there for a reason, entirely valid if the reason for them is valid, so yes, just use them. However: 400 means Bad Request, which means the input is syntactically wrong. You should send a more appropriate header (like 409 for a conflict, 428 for a failed precondition, etc.). I'm struggling to come up with a project with a valid use for 418 I'm a teapot, but I will succeed some day..
Anybody interested in the inner workings of your site could look at the console, but there should be no problem with this, nor should you overly pander to a clean look there, just make sure your own process flow is sound.

Categories