Meaning of callback parameters in node.js code - javascript

I'm very new to Node.js and I'm just trying to make sense of how the parameters work in the callback methods of the code.
I can only understand the first one, function(req,res), because I've used that in Java when working server-side, but I don't really understand how it automatically calls the memcached function or how that kicks off the rest, etc. If somebody could explain to me how this works I'd really appreciate it. Thank you
server.on('request', function(req, res) {
//get session information from memcached
memcached.getSession(req, function(session) {
//get information from db
db.get(session.user, function(userData) {
//some other web service call
ws.get(req, function(wsData) {
//render page
page = pageRender(req, session, userData, wsData);
//output the response
res.write(page);
});
});
});
});

It could roughly be compared to passing the anonymous class in Java. For example to sort a collection in Java you pass a comparator class which has a method for comparing two objects. Later, when sorting algorithms needs to compare the objects it calls the function in provided class.
In javascript functions are first class objects, which means we don't need a "wrapper" class and can pass it as a parameter to another function.
In your case "memcached.getSession" will execute is't logic, find the session, and calls the anonymous function you pass in the second parameter, with the session as parameter.

Related

How to receive default arguments in a javascript function like node or express HTTP functions?

In express.js when we call
app.get(function(req,res){...}),
the function automatically receives request and response objects and we can give any name to function parameters like req,res or re,rs and many others.
I want to create a function that will rest in an object.
When I want to use this function it must receive default arguments which may be e.g simple int 4,3 and I must be able to specify parameter names as per my choice.And these arguments must be assigned to parameter names I have defined and I must be able to use those name in code inside function.
How can I achieve this?
You can write your own middleware for this. For example this is how I control the mandatory fields in requests :
router.post('/relations', controlBodyMiddleware(['userIdReceiver']), relation.create);
While you can have method like this :
controlQueryMiddleware(fields) {
return function(req, res, next){
if (!req.body.mandatoryField || req.body.mandatoryField !== 5){
return next(new Error('I want mandatoryField equal to 5'));
}
req.body.myFieldAccessibleInNextMiddleware = 'Yes, this would be there';
next();
};
}
I have found the solution myself.
It was all related to call back functions and passing the function definition to another function.
var app={
get:function(callback){
callback('Request object..','Response object..');
}
};
app.get(function(rq,rs){
console.log(rq,rs);
});
Here we can pass function definition in get method with parameters of your own choice that's what I wanted to know.
It is not necessarily express object or methods.
app can be any object and get can be any method of app.
With of course parameters not necessarily req and res objects.

Javascript, where does your 'magic' data come from?

Coming from the Java Programming Language where all information that can be used in a method must either be part of a class, or passed by parameter, I'm very confused on to where JavaScript magically generates it's very important data.
In this case I'm using Socket.IO and trying to call a login-method after connection, now I could just use an anonymous function, but I personally believe they're really ugly.
Here's my code:
socketIO.sockets.on('connection', function(socket) {
console.log("Connection maid.");
socket.on('login', login);
});
function login(json) {
sqlConnection.query('select * FROM Accounts', function(err, rows, fields) {
if(err) throw err;
for(var row in rows) {
if(rows[row].Username == json.username) {
console.log("Exists");
socket.emit('login', {nuel: ''});
}
}
});
}
As you can see the login function is called whenever the socket receives a login message, and the json object is magically passed to it. I have no idea where it comes from or what generates it, nor do I have a clue how to pass additional arguments to the method, because it breaks/overwrites the magic data.
The error I'm running into is where socket doesn't exist in the current context, because it was not passed to the login function, however when I try to pass it, the object saved as json is completely eradicated from existence.... AND WHERE IS THE DATA THAT'S HERE COMING FROM.
I don't understand this at all, How can I pass this information to call the method, without completely breaking everything.

Using apply to send multiple arguments to server

I'm working on a javascript client in angular that uses SignalR to communicate with a backend server. The basic idea is that you can do remote procedure calls on the server from the client and vice versa. I have an appropriate abstraction for calling a server method that takes no parameters as follows:
myInvoke: function (methodName, callback) {
proxy.invoke(methodName)
.done(function (result) {
$rootScope.$apply(function () {
if (callback) {
callback(result);
}
});
});
}
The important part being proxy.invoke(methodName) which takes the name of the server method to call as a string.
proxy also allows passing multiple arguments to invoke. Some examples from SignalR documentation:
// one parameter
contosoChatHubProxy.invoke('newContosoChatMessage', { UserName: userName, Message: message}) ...
// two parameters
contosoChatHubProxy.invoke('NewContosoChatMessage', userName, message) ...
What I'd like to accomplish is something more like this where args is any number of arguments that should be forwarded on to the hub:
myInvoke: function (methodName, args, callback) {
proxy.invoke(methodName, args)...
I've been reading about the apply method but my javascript is pretty weak and I haven't been able to come up with a working implementation.
Ignore my previous comment. I misread the SignalR doc you included. Basically I was assuming you could always pass a single object parameter. It does look like you can accomplish what you want by doing
See this jsbin for how to use apply to pass the arguments from the current function to the invoke function.
http://jsbin.com/juqanigulo/1/edit?html,js,console,output

Called a stored javascript function from Mongoose?

I have created a stored javascript function in my MongoDB instance that counts the number of records in each collection. If I go to my mongo shell and type:
> db.eval("getTotals()");
it works as expected. if I try to call it through mongo like so:
totals = mongoose.connection.db.eval("getTotals()");
console.log(totals);
undefined gets logged. Does anyone see what I am doing wrong here?
Most mongoose calls do not return in-line like this, but rather expect a callback to be passed in to process the results.
Completely untested, but you probably want something like:
mongoose.connection.db.eval("getTotals()", function(err, retVal) {
console.log(retVal)
});
And in the real world, assign your result to a var outside of that scope or whatever you want to do.

Can you return an SQLResultSet with JavaScript from an SQLite database?

I'm trying to create a little plugin that will make working with SQLite databases a little easier. I've got the basic CRUD functions except for selecting data from the database.
I would like to return the selected data from the executeSql function, but it seems all I can do is call another method and not just return the data.
So what I'd like to do is:
var data = $(window).dbPlugin( 'select', '*', 'tableName', 'conditions' );
Then I would like to work with the "data" variable as the SQLResultSet from the query. However, the transaction seems to only allow me to call a data handler method and not just return the result.
testDB.transaction(
function ( transaction ) {
transaction.executeSql( sql, [], dataHandler, errorHandler);
}
);
function dataHandler( transaction, results ) {
// Now I can work with the "results" as the SQLResultSet
}
Any ideas how to just return the selected data or if it's even possible?
SQLlite is asynchronous, and there isn't any way to avoid that. You could pass in the function you want to be called as your callback into your .dbPlugin method. After conditions pass another value which is a function to be called after the query is run. Then set data in your callback function.
It's pretty annoying, I recently wrote something like you are writing on my last project. I used a jQuery plugin called blockUI that would essentially block the interface during SQL calls which made it appear a little more 'synchronous'
Good luck.

Categories