node.js - can someone explain this callback? - javascript

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.

Related

How does Javascript callback use external variabile that has to be still created

I'm new to nodejs, I've come across this function in express
var server = app.listen(()=>{
console.log(server.address())
})
How does the callback use the returned object from the listen function, can someone explain me the mechanism behind this code? Thanks
Perhaps it helps to rewrite the code into the following equivalent code:
var server;
function logServerAddress() {
console.log(server.address());
}
server = app.listen(logServerAddress);

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

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

Express - better pattern for passing data between middleware functions

I just brought up this issue with Express and I am interested in what StackOverflow thinks about it:
https://github.com/strongloop/express/issues/2831
my question is why Express opts to disallow the developer from passing data directly between middleware functions and basically forces you to assign temporary data to the request object in what I have always considered to be a quite awkward assignment.
to be more specific:
passing data between middleware functions usually involves doing this
req.specialData = {}
next();
however, it would be perhaps much easier and more performant (!) if this were possible
next(null,data);
or
function mySpecialMiddleWare(req,res,next,data){}
//now, call the above function
mySpecialMiddleWare(req,res,next, {some:data});
the problem is that Express uses a, what I believe to be, stupid way of determining if the call is to a normal middleware function or the next error first middleware function, by checking to see if the function.length > 3 or function.length === 4...
is there any chance what I am saying makes any sense?
wouldn't it be better/easier/faster/stronger to allow direct passing of data via middleware functions instead of assigning data awkwardly to req ??
perhaps Express already has this capability and I am just misinformed?
my question is why Express opts to disallow the developer from passing data directly between middleware functions and basically forces you to assign temporary data to the request object in what I have always considered to be a quite awkward assignment.
So I think the API is the way it is to encourage most middleware to be modular, re-usable, and loosely coupled. That means the generally should do something without being concerned too much about what other middleware might run before them or after them. In order to achieve this and create an ecosystem of loosely-compatible middleware functions, express keeps the API fairly generic. There are pros and cons to this. But as a direct answer to your first question, I would say to keep the interface simple, consistent, and flexible as well as try to avoid strict ordering dependencies.
As in your case, there might be implicit dependencies between middlewares. Another common example would be typically your session middleware has an implicit dependency that your cookie middleware runs before it. Having these all be implicit can be argued to create bugs and unnecessary troubleshooting. On the other hand, it enables application developers to more easily mix and match middlewares that might otherwise have no awareness of one another.
In hindsight I think both I as well as some of the express maintainers would agree that using function arity (number of expected arguments) for semantic API reasons was an odd and poor choice on TJ's part. I think if the project were to be rewritten a more explicit API would be defined for error handling.
wouldn't it be better/easier/faster/stronger to allow direct passing of data via middleware functions instead of assigning data awkwardly to req ??
Better - this is highly arguable and opinion based. There is a lot to be said for the simplicity of it and the evidence is the huge ecosystem and usage. There are alternatives available such as hapi, restify, etc, though so you might consider them.
Easier - probably not. What's there is pretty easy.
Faster - probably not in any meaningful way. Not sure why you think your version would be faster, but best to bring metrics when you make such claims.
Stronger - If by "stronger" you mean more explicit that's probably true but there's a reason some people still prefer JavaScript even though TypeScript all the way up through Haskell exist and are definitely "stronger" in some sense of the word.
There might be advantages to what Express is doing, however, it is worth noting that Express allows passing data between middlewares using res.locals. With that said, your question inspired me to make this library. Expressjs-plus.
With it, you will be able to pass data between your middlewares easily without having to use the request nor the response object.
You can use regular javascript functions e.g. function(varInResLocals, varInReqParams, callback) instead of express middleware signature.
Here is a working example for you.
var express = require('express');
var ExpressPlus = require('expressjs-plus').ExpressPlus;
var app = express();
// simple handler example
var userHandler = function(param, paramsArray, req, res){
if(param !== 'user') return false;
paramsArray.push("USER WAS FOUND!");
return true;
};
// this handler allows you to pass res.locals properties between your middlewares seemingly,
// it the parameter was found in locals, it attaches it to paramsArray.
var resLocalsHandler = function(param, paramsArray, req, res){
if(param in res.locals){
paramsArray.push(res.locals[param]);
return true;
}else return false;
};
var appPlus = new ExpressPlus(app, [userHandler, resLocalsHandler], []);
var regularFunction = function(user, id, cb){
return cb(null, { response: {user: user, id: id}, status: 200, resLocalsVar: "passVar" });
};
// resLocalsVar was passed in a previous method
var regularFunction2 = function(resLocalsVar, user, id, cb){
// now you can have access to it
console.log(resLocalsVar);
return cb(null);
};
// the responder at the end will use res.locals.status and res.locals.response to issue an HTTP response
app.use(appPlus.GMV(regularFunction), appPlus.GMV(regularFunction2), appPlus.responder);
// adds error handlers, it will add a default error handler along with the list of error handlers passed
// in this case, no error handlers were passed
appPlus.setErrorHandlers();
app.listen(3001, function(){
console.log('Listening!');
});

object oriented development in node.js

Created a api server by using nodejs. as a habit from frontend development, developed them in object oriented structure but i'm confused in one point while writing.
var server = {
component: {
http: require("http"),
fs: require("fs")
},
start: function () {
var instance=this;
this.component.http.createServer(function (request, response) {
instance.component.fs.readFile(filename, "binary", function (err, file) {
// do something with file
});
}).listen(80);
}
That's my method to call inherited object within parameter function. in this case is single filesystem object sharing with all connections or do i need create a new filesystem instance for each new connection?
edit: "instance" is not a labeled statement.
In your example filesystem object will be reused for each connection.
Advice regarding style of coding: I am pretty sure you don't need 'instance' labeled statement - in fact I would strongly discourage you from using it in js at all! Labeled statements are usually used with break or continue statements & in fact have seen them in use only few times in my whole career. They make mess in code & can confuse someone who is reading your code. You can read more about label statements in MDN JavaScript manual.
As a replacement of label here use e.g. variable. Also if you will start assigning 'this' to e.g. variable (or label in your example) try to stick to that & immediately start referring to this variable - try not to mix 'this' & variable containing it (like in line 8 of your code). Your code can then look like this:
var server = {
component: {
http: require("http"),
fs: require("fs")
},
start: function () {
var instance = this;
instance.component.http.createServer(function (request, response) {
instance.component.fs.readFile(filename, "binary", function (err, file) {
// do something with file
});
}).listen(80);
}
Object scope will isolate 'instance' here & allow it deeper in 'instance.component.http.createServer' callback.
Hope this answer & advices will help you & other JavaScript devs!

Deps autorun in Meteor JS

Decided to test out Meteor JS today to see if I would be interested in building my next project with it and decided to start out with the Deps library.
To get something up extremely quick to test this feature out, I am using the 500px API to simulate changes. After reading through the docs quickly, I thought I would have a working example of it on my local box.
The function seems to only autorun once which is not how it is suppose to be working based on my initial understanding of this feature in Meteor.
Any advice would be greatly appreciated. Thanks in advance.
if (Meteor.isClient) {
var Api500px = {
dep: new Deps.Dependency,
get: function () {
this.dep.depend();
return Session.get('photos');
},
set: function (res) {
Session.set('photos', res.data.photos);
this.dep.changed();
}
};
Deps.autorun(function () {
Api500px.get();
Meteor.call('fetchPhotos', function (err, res) {
if (!err) Api500px.set(res);
else console.log(err);
});
});
Template.photos.photos = function () {
return Api500px.get();
};
}
if (Meteor.isServer) {
Meteor.methods({
fetchPhotos: function () {
var url = 'https://api.500px.com/v1/photos';
return HTTP.call('GET', url, {
params: {
consumer_key: 'my_consumer_key_here',
feature: 'fresh_today',
image_size: 2,
rpp: 24
}
});
}
});
}
Welcome to Meteor! A couple of things to point out before the actual answer...
Session variables have reactivity built in, so you don't need to use the Deps package to add Deps.Dependency properties when you're using them. This isn't to suggest you shouldn't roll your own reactive objects like this, but if you do so then its get and set functions should return and update a normal javascript property of the object (like value, for example), rather than a Session variable, with the reactivity being provided by the depend and changed methods of the dep property. The alternative would be to just use the Session variables directly and not bother with the Api500px object at all.
It's not clear to me what you're trying to achieve reactively here - apologies if it should be. Are you intending to repeatedly run fetchPhotos in an infinite loop, such that every time a result is returned the function gets called again? If so, it's really not the best way to do things - it would be much better to subscribe to a server publication (using Meteor.subscribe and Meteor.publish), get this publication function to run the API call with whatever the required regularity, and then publish the results to the client. That would dramatically reduce client-server communication with the same net result.
Having said all that, why would it only be running once? The two possible explanations that spring to mind would be that an error is being returned (and thus Api500px.set is never called), or the fact that a Session.set call doesn't actually fire a dependency changed event if the new value is the same as the existing value. However, in the latter case I would still expect your function to run repeatedly as you have your own depend and changed structure surrounding the Session variable, which does not implement that self-limiting logic, so having Api500px.get in the autorun should mean that it reruns when Api500px.set returns even if the Session.set inside it isn't actually doing anything. If it's not the former diagnosis then I'd just log everything in sight and the answer should present itself.

Categories

Resources