Node.js Should Functions be Declared outside of other functions? (With express) - javascript

Because Node runs the code inside a require call and then exports the members defined in it, it seems like it would be better to define functions outside of functions when that module is required or used multiple times.
For instance, take the following two codes using express:
router.get('/', function (req, res) {
function logTest () {
console.log('log test');
}
});
And
function logTest () {
console.log('log test');
}
router.get('/', function (req, res) {
logTest () {
});
It seems like the code in the second answer would be more efficient because logTest is only defined one time as opposed to being defined every time a get request is made. Is this true? Are there any best practices about where to define these functions?
I have looked around other answers and not found anything that really gets to my question here.
EDIT:
In addition to performance gains, (for which, in Node, the answer seems to be little to none) I am interested in style / maintainability and if one technique is preferred to the other in this respect.
Thank you

Related

How to make a proper logging in nodejs

I Have a service that uses wrapper class for Winston logger to log the HTTP calls, internal failers, and so on to be able to maintain the service on production
the behavior of logging is something like this
function getUser(req, res, next) {
try {
logger.info("user::api::getUser", "controller called");
// do some stuff here, call the service related and return response
} catch(err) {
logger.error("user::api::getUser", err);
}
}
and also this logger is called in all subsequent functions along with the app, such as services, db access layers, controllers, middlewares, and so on
Actually, I am disappointed about calling logger in each function I write which I feel like polluting the code and don't make single responsibility principle also makes the code violates closed to modification principle` since if I updated the logger API for example, then I have to go through all the functions that the logger used inside and update it to the new syntax which is not good
I thought about if I can use event-driven, I mean event emitters to emit events on each failure, call and the handlers of these events will write the appropriate log
for example something like this
function getUser(req, res, next) {
try {
eventEmitter("info", "controller called");
// do some stuff here, call the service related and return response
} catch(err) {
eventEmitter.emit("error", err);
}
}
and here is the listener
eventEmitter.on("error", (err) => {
logger.error("error", err);
});
I see this syntax hides the implementation of calling the logger into one function instead of calling it in each part of the app, but still, the functions are polluted because I still have to call the event emitter inside them to emit logging event
I don't know if there is an intelligent way to implement logging without calling the logger in each part of the app like this !!
Also, I am wondering how giant companies handle these cases in their applications
I hope someone respond to me and guide me to the right direction

NodeJS : how to use arguments like req, res, result in functions?

I'm fairly new to JS especially Node and Express. I am following some tutorials on how to build an API and at the same time learning about JS special features such as let/const/var, arrow functions etc.
In many tutorials I have seen things likes this :
somecode.then((result) => {someothercode})
With: "somecode" being for example a get request
Is "result" the name of the returned value or is it a convention that JS developper use?
By that I mean, does this for example work?
somecode.then((foo) => {someothercode})
Also for req, res variables what does this mean?
app.get("/users/:userId", [
usersController.getById
]);
Here is the getById function (using once again the "result"):
exports.getById = (req, res) => {
userModel.findById(req.params.userId).then((result) => {
res.status(200).send(result);
});
};
the getById method defined in the controller needs (req, res), does that mean, when i call it like the code above, the req and res arguments are implicitly used?
Also it needs a parameter :
req.params.userId
which is in the url of the route, how does it pass to another file?
I have a route.js file that uses a controller.js file that uses a model.js. How does the param go from route to controller?
And it won't work if I change the param name right? for example:
req.params.id
Sorry for long post, I'm trying to understand JS logic to get some good habits and write clean code.
Thanks!
Is "result" the name of the returned value or is it a convention that JS developper use? By that I mean, does this for example work?
From my experience, yes - result is often used. Often times you'll see thing like value, response, but ultimately it can be whatever you define. I would recommend sticking to convention, and also check out the MDN Promise tutorial if you are starting out with understanding NodeJS asynchronous operations.
Also for req, res variables what does this mean?
app.get("/users/:userId", [
usersController.getById
]);
That is a middleware chain. Check out the Express docs for more information.
the getById method defined in the controller needs (req, res), does that mean, when i call it like the code above, the req and res arguments are implicitly used? Also it needs a parameter :
req.params.userId
which is in the url It won't work if I change the param name right? for example:
req.params.id
Yes, that is using a named parameter. Without the full router code, it is hard to know how the getById method is linked to the defined route. The Express routing documentation will likely be a good start on that.
Is "result" the name of the returned value or is it a convention that JS developper use?
result is the name of a new variable you are creating to represent the value passed in from the Promise resolution. Yes, your foo example will work.
(req, res) => {} is the same (mostly) as a function that looks like this:
function getById(req, res) {...}
req, and res are just representational of the values that will be passed to this function. They could just as easily have been called (foo, bar).
It looks like you're struggling with understanding callback functions. Consider the following code then please crack open the source code for the packages that you are using. and it looks like you are using express.js
function something(callback) {
var x = 5;
var y = 'anything';
callback(x, y);
}
something(function(req, res) {
console.log(req);
console.log(res);
});
the something function is created and inside of that function scope, var x and y are created with any type. then when we invoke or use something function we are passing a function as a variable that gets passed in as variable callback then it can be used since it is a function so we call callback with x and y which can literally be any value and for effect, I am passing back a number and a string as req and res.
It's just a convention. Note that the code:
somecode.then((result) => {someothercode});
Is actually:
somecode.then(myFunction);
Since somecode is a Promise, your function may be called with zero or one argument. It is up to you to name this argument:
function myFunction (foo) {
// use foo here
}
somecode.then(myFunction);
Of course, unlike some other languages, javascript does not force you to name your function. You can just use a nameless (anonymous) function:
somecode.then(function(mango) { /* use mango here */ })
Arrow functions is a new syntax allowing you to write anonymous functions in a shorter style (it also behaves slightly differently with regards to scope and the value of this)
Express.js and http.Server
In node's http.Server library and Express.js framework, each server request will call a function you define and pass it two arguments: the request object and the response object. The variables req and res are just conventions people use when writing their own request handler functions. You can name them anything you like. For example you may prefer to use request and response instead or rx and tx:
app.get('/say/hello', (rx, tx) => tx.send('Hello'));
How many arguments do I write a callback function with??
The best way to know is to read the documentation of the module you are using. It is not the only way to know - you can of course read the source code instead. But it is often easier to read the documentation. Because of this, javascript modules tend to have really good documentation (otherwise they would be unusable and ignored by the community).
Express.js will actually pass three arguments to your callback (not two!!) - request, response and next where next is a function you can call if you want Express to continue processing instead of replying to the request. One interesting feature of javascript is that you are allowed to call functions with fewer or more arguments and it is not considered a syntax error:
function example (x) {}
example(); // not an error
example(1); // not an error
example(1,2,3,4); // also not an error
Express uses this feature by always calling your callback with three arguments while allowing you to declare said callback with only two arguments if you don't need the third, next argument.

node.js - can someone explain this callback?

There's more than one node.js tutorial out there, demonstrating how to create a server. But, they're coded in different ways. So, how do you know when to write it one way, versus another? None of the tutorials explain why they wrote it the way they did.
For example...
Example 1:
// Create an http server, passing in a function for some reason:
http.createServer(function(request, response) {
versus Example 2:
// Create an http server, and then start it
var server = http.createServer(handleRequest);
server.listen(PORT, function () {
Thanks in advance. I'm really having trouble understanding this.
They're no different, really. In the first, you're defining the function for handling a request on the spot then have to start listening at the end.
http.createServer(function(request, response) {
...
}).listen(PORT, function() { ... });
In the second, you define the function for handling a request elsewhere and don't use chaining.
function handleRequest(request, response) {
...
}
var server = http.createServer(handleRequest);
server.listen(PORT, function() { ... });
They both do the same thing. It just depends on how you want to write it.
Preference really.
Some prefer to handle the function definition within the argument list (typical of the older documentation as well) while others prefer to pass in the name of an already defined function.
I find the second example easier to maintain and more flexible but it really boils down to preference.

Custom event listeners in an express route

What is the best way of handling custom event listeners in an express route?
I'm probably doing it all wrong but here's what I have at the moment:
module.exports = {
get: function(req, res, next) {
MyModel.on('error', function(err) {
res.send(501)
})
MyModel.on('found', function() {
res.send(200)
})
MyModel.on('notFound', function() {
res.send(404)
})
MyModel.findByName(req.params.name);
}
}
I can see this is totally wrong since each event listener will be added on each request.
It also feels wrong to start passing the response object around to facilitate responding when an event is fired.
I could just use callbacks on the findByName method but I really like tying into the event system but I'm just wondering how to handle this situation better.
Don't use event bindings for this, use the callback function:
module.exports = {
get: function(req, res, next) {
MyModel.findByName(req.params.name, function (error, model) {
if (error) {
return res.status(501).send(error);
}
if (!model) {
return res.status(404).send('Not found');
}
res.send(model.toJSON());
});
}
}
To add some clarification based on the comments, your example is using express and mongoose, both by the same original author and both primarily oriented with functional style programming and callbacks. While it is possible to design frameworks to use events, callbacks, or both/either (optional), in these 2 specific cases the library forces you to use callbacks because it doesn't provide events for these particular operations. That's why for express and mongoose for these particular calls, callbacks are the idomatic thing.
Now looking at your example, mongoose does emit some events at the Model class level, but those are not associated with an express request/response and thus are more appropriate for error logging and exception handling and some other specialized use cases outside of basic web application response rendering.
So when I said "don't user event bindings for this", I didn't mean event bindings are never appropriate, just that given your specific code snippet, they are neither supported by the libraries you are using nor idiomatic for this example of a basic make-a-db-query-and-send-back-a-web-page scenario.

Most efficient way to define Socket.io on("message") handlers

Socket.io's examples all follow this pattern
io.sockets.on("connection", function(mySocket){
mySocket.on("my message", function(myData){
...
});
});
It seems to me that this would create a new callback function for every connection. Assuming that every socket responds to the message in the same way, wouldn't it be more memory efficient to define the handler once for all sockets like this:
function myMessageHandler(data){
...
}
io.sockets.on("connection", function(mySocket){
mySocket.on("my message", myMessageHandler);
});
or even this:
io.sockets.on("my message", function(mySocket, myData){
...
});
If so, why would Socket.io recommend a practice that wastes memory? Are we expected to want to keep stateful variables for the socket inside the "connection" callback's closure?
Looking at it from another perspective, the first form is easy to read (because so many details are left out). I think this form best illustrates how the library works. Similar style is used on the Node website itself for the same reason, I believe. And I think that's precisely why it is used in those places.
After a few minutes reading blogs and discussions suggests that developers are usually opting for passing around named functions. Although I'm sure there's a performance gain in it, the primary motivation is no doubt readability. I think you'll find the second form (or a more drawn out form) to be easier to work with as your functions grow.
Defining Socket.io in most efficient way:
io.on('connection', function (socket) {
socket.on('new-message', function (data) {
io.emit('emit-message', data)
});
});
Or
io.on('connection', (socket) => {
console.log('user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});

Categories

Resources