Where are the `req` and `res` coming from? - javascript

NOTE: This question has very little jQuery, Drupal, or node.js it's more of a generic question on "how frameworks achieve X, where X is something any of the frameworks I mentioned also provides.
I saw an example node.js code that looks like this:
var http = require('http');
var server = http.createServer();
server.listen(8000);
server.on('request', function(req, res) {
//do something with req and res here
});
There is no obvious place where req and res are coming from. In fact, what does 'request' mean? Where is it supplied from?
I have noticed similar things in jQuery .get() and .post() functions, and looking at the source did not help as much as I would like. I've even seen this being done in Drupal; a function is defined in the theme layer or as a module_hook with specific naming conventions by me, but arguments appear outta nowhere and there is a predictable structure of data (specified in the manual) inside those magic variables.
So what is this technique called, and how does it work. I've heard tell of Dependency Injection... is this it? If it is, could you explain in n00b terms how it is accomplished?
This is particularly confusing because I coded in procedural from the start, and we always know where a variable is coming from and how a function is being called...

The framework constructs the objects for you, and passes them to your callback.
N.B. req and res are just parameter names; you could call them spam and eggs, or hocus and pocus, for all it matters.

In fact, what does request mean? Where is it supplied from?
Whenever you want to access a web site, you're using a special protocol, the hypertext transfer protocol (HTTP). This protocol mainly uses two things:
a question from the client like "what is / on your server?" (the request)
an answer from the server like "it's a text/html, the length is 2000 bytes, and here is the document" (the response).
This request-response model is used directly in node.js, as the server you're using is a HTTP server.
[...] could you explain in n00b terms how it is accomplished?
Do you know what a main-loop or event-loop is? Almost every GUI application has one. It's basically a loop like this:
while(waitForNewEvent(&event)){
handleMsg(&event);
}
This event can be anything, from keyboard input to another software trying to bring your window to front. It can also be something like "are you ready for standby?".
node.js uses such a event-loop in it's server implementation. server.on('request', callback) basically tells node.js that you want callback to be used whenever a request is coming:
while(waitForNewEvent(&event)){
if(event == "request"){
callback(request,&response);
responseToClient(response);
}
}
Intern example
Or even simplier: think of a intern, who's just running around in circles in a building. He's the event-loop. Now in your server room someone tells him that every request should be brought to them. He writes this down and continues on his never-ending tour.
Then someone stands in front of the building and wants to check his bank-account. He simply throws a request into a post box and the intern rushes to the server room and tells the technicians that the specific site has been requested and gives them the necessary information. However, he needs to wait on their response, since their response isn't on his list.
The technicians check the request and find out that the user isn't qualified for the given request(*). They prepare an error message and give it to the intern. He now returns to the front of the building, gives the error message to the first client and is ready for other messages.
(*): At this point they might need to check something in a database, which might take some time. They could tell the intern to come back later and call him if they're ready. In this case the intern could continue his way until the technicians are ready.

You're passing the function to the .on() function. When the event occurs, some internal code invokes the function you passed, and provides the arguments to it.
Here's an example. The server object has a method named on. It takes a name string and a callback function.
It uses setTimeout to wait one second before invoking the callback it was given. When it invokes it, it passes to it the name that was provided, as well as a static message "hi there".
// Think of this as the internal Node code...
var server = { // v---this will be the function you pass
on: function(name, callback) {
setTimeout(function() {
callback(name, "hi there"); // here your function is invoked
}, 1000);
}
};
So here we call .on(), and pass it the name "foo", and the callback function. When the callback is invoked, it will be given the name, and the "hi there" message.
// ...and this is your code.
server.on("foo", function(name, message) {
console.log(name, message);
});

They are short for "Request" and "Response." It is typical of many web frameworks to pass these two objects into a request handling method (action or whatever you want to call it).

Related

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?

Meteor.call (Meteor.methods) seem to run on both client and server--causing issues

I execute Meteor.call from the client side to a Meteor.methods method and as I console.log things, they are logged in both the command prompt and the browser console.
The issue with this is that it actually seems to be executing on the client side--which does not have access to the proper entities. While I get no errors on the command prompt, here's what is shown on the client side:
Exception while simulating the effect of invoking 'createInvite'
Meteor.makeErrorType.errorClass {error: "not-found", reason:
"evaluator_invite__entity_not_found", details: undefined, message:
"evaluator_invite__entity_not_found [not-found]", errorType:
"Meteor.Error"…} Error: evaluator_invite__entity_not_found [not-found]
at Meteor.methods.createInvite (http://localhost:3000/lib/collections/invites.js?505cdea882e0f829d521280c2057403ec134b075:38:15)
Is it actually running on the client side? Should this error be there?
Meteor methods are expected to run on both environments if defined globally, this allows for a nice feature which is called latency compensation.
The whole latency compensation concept is off topic but basically it means simulating client-side what the server would actually do like inserting documents in the database right-away to design fluid UX. You're essentially predicting server behavior before it's even happening to make your client experience ultra-responsive by eliminating network latency.
An example of this might be inserting a comment in the database immediately after the user submitted it. In this case the Meteor method calls getting executed on both the server and the client will share the same code.
Sometimes it makes absolutely no sense to provide a client-only simulation - or "stub" - when designing a method responsible for sending emails for example.
Some other times it makes sense to share some part of the code but you need to access environment specific objects : for example a method to insert comments might use Email.send on the server to notify an author a comment has been added on his post.
Meteor.methods({
insertComment: function(comment){
check(comment, [...]);
if(! this.isSimulation){
Email.send([...]);
}
return Comments.insert(comment);
}
});
Ultimately, you have to structure your code differently depending on how your method is supposed to behave.
For server-only methods, define them under the server directory, with no client-side counterpart.
For shared methods that can share exactly the same code on both environments, just define them globally.
For shared methods that just slightly differ, you can use Meteor.isClient / Meteor.isServer or method only property isSimulation to check against the current environment and execute specific code accordingly.
For shared methods that share little to no code, I personally use a pattern where I define the Meteor method on both client and server environment and take care of shared behavior like checking arguments validity, then I call a function responsible for actually implementing the correct behavior.
lib/method.js
Meteor.method({
method: function(args){
check(args, [...]);
//
return implementation(args);
}
});
The trick is to define the implementation separately on client and server, depending on the context, the correct function will get called.
client/method.js
implementation = function(args){
// define your client simulation / stub
};
server/method.js
implementation = function(args){
// define your server implementation
};
Read how to structure your app: http://docs.meteor.com/#/full/structuringyourapp
If you want your methods to be run only on the server, put files with methods into server folder.
If you want latency compensation you can use conditionals in your methods:
Meteor.methods({
method1: function() {
if (Meteor.isClient) {
//Do client side stuff
}
if (Meteor.isServer) {
//Do server side stuff
}
}
});

How to unit test web sockets - JavaScript

I would like to test web sockets that have been implemented using sockjs.
var sock = new SockJS('http://mydomain.com/my_prefix');
sock.onopen = function() {
console.log('open');
};
sock.onmessage = function(e) {
console.log('message', e.data);
};
sock.onclose = function() {
console.log('close');
};
I goggled and only found this article. This is not good enough because it's making actual connection rather than faking it.
I also tried SO but only found an unanswered question here.
Someone suggested sinonjs but I'm not able to find any decent example.
I'll appreciate if someone can shed some light on this topic.
When you want to unit-test a feature which accesses an external resource, like in your case a websocket server, the usual approach is to use a mock-object to represent the external resource. A mock-object is an object which looks and behaves like the external resource, but doesn't actually access it. Additionally, it can have logging functionality which allows it to report to the test-code if the tested code behaved like expected.
In your case you would create a mock-SockJS object which has all the relevant properties and methods of a normal SockJS object, but its implementation doesn't actually contact a server. It only logs the method calls and returns the expected response an existing server would send.
Then you would refactor the code you want to test so that it doesn't create the socket itself but instead gets a socket object assigned from the outside (this is called "dependency injection" and is a crucial idiom for writing unit-testable code).
In your real code, you assign a real SockJS object. But in your unit-test, you assign your mock-object. After you called your test-methods you can examine the mock-object to check if the unit sent the expected data to the server.

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.

Correct use of socket.io events's callbacks

I was reading this interesting introductory article about how socket.io's events and callbacks work.
I decided to give first try with something as follows.
First try
server.js
// client is the socket for the client
client.on('foo' , function(callback){
callback("Hello world");
});
client.js
// server is the socket for the server
server.emit('foo', function(msg){
alert(msg);
});
Well, it just so happens that it actually didn't work (the server throws an exception telling callback is not a function). Trying to solve that, I found this answer explaining how to do it the right way. Well, that didn't work either. A few modifications and I got to this...
Second try
server.js
// client is the socket for the client
client.on('foo' , function(name, callback){
callback("Hello world");
});
client.js
// server is the socket for the server
server.emit('foo',{},function(msg){
alert(msg);
});
Well, it works perfectly, but having to add that "name" parameter and that empty hash which I don't use seems to be a a not-so-good solution.
I tried to find the explanation of this in the amazingly incomplete socket.io's documentation, but found no explanation for this beheaviour, which is why I'm asking here.
Another doubt that I have is if it possible to do the same to the other side (i.e., the server sending a callback to the client, and then the callback getting executed in the server), but I haven't tried yet.
TL;DR: Why the first try doesn't work and the second one does? Is there a way to avoid that useless empty hash and name argument?. Does this work the same the both ways? (server→client and client→server).
The empty object doesn't have to be an object, it can be virtually anything, such as a string, or maybe even null (haven't tried that). Also the name parameter isn't specifically a "name" parameter, it's simply whatever data you passed from the client (again, that could be the empty object you are currently using, or anything else). A better generic parameter name might be data. Sure, you could call it a waste, but it's only two characters that you're transferring, and most of the time you'll probably find a use for that data.
The third argument you're passing to emit (a function) is the optional callback parameter, and obviously since it's working, you're using it right.
As to going in the reverse direction, I've never tried that either. It's likely to work, but even if it doesn't, all you have to do is send a unique ID along with each of your push events, and then have the client emit an event back to the server with that ID, and write some code on the server which reassociates that event with the original push event. You could even use a counter on each socket as your push ID, and then use the combination of socket.id and event.id as a unique identifier.

Categories