How does the "response" and "data" get passed to then() [duplicate] - javascript

I understand the essence of callback functions in that the function is executed again after being passed as the parameter to another function. However, I'm confused as to where the variables inside the callback function come from as shown in the following node.js example:
router.get('/', function(req, res){
res.render('index', {});
});
How do the variables req and res get populated? An example explaining how I can just call res.render(...) without declaring res myself would be greatly appreciated.

They come from the same place they come from when a normal non callback function is invoked, at invocation time.
If you have this function,
function add (a, b) {
return a + b
}
You're fine with knowing that a and b come from when you invoke add,
add(1,2)
and it's the same principle with callbacks, don't let your brain get all twisted just because it's getting invoked later.
At some point the function you pass to router.get is going to be invoked, and when it does, it will receive req and res.
Let's pretend the definition for router.get looks like this
router.get = function(endpoint, cb){
//do something
var request = {}
var response = {}
cb(request, response) // invocation time
}
In the case of your example, it's just up to node to pass your function request and response whenever .get is invoked.

The whole point of the callback is that the invoked function calls it back.
In the case of router.get, it will insert the route (path, method, callback) in a lookup table; when a request comes in, Express will construct the response object, match the request's path and method against all the entries in the lookup table, take the callback from the matching entry and invoke callback(request, response) (passing the detected request and created response).

They get populated by whatever code is calling the callback. In your example, this is something inside the Express framework, though Express uses the node http library under the hood and adds additional functionality to the request and response objects provided by it.
But in code you write you can create a callback function signature that takes whatever params you want.

Related

How this variable gets value [duplicate]

I understand the essence of callback functions in that the function is executed again after being passed as the parameter to another function. However, I'm confused as to where the variables inside the callback function come from as shown in the following node.js example:
router.get('/', function(req, res){
res.render('index', {});
});
How do the variables req and res get populated? An example explaining how I can just call res.render(...) without declaring res myself would be greatly appreciated.
They come from the same place they come from when a normal non callback function is invoked, at invocation time.
If you have this function,
function add (a, b) {
return a + b
}
You're fine with knowing that a and b come from when you invoke add,
add(1,2)
and it's the same principle with callbacks, don't let your brain get all twisted just because it's getting invoked later.
At some point the function you pass to router.get is going to be invoked, and when it does, it will receive req and res.
Let's pretend the definition for router.get looks like this
router.get = function(endpoint, cb){
//do something
var request = {}
var response = {}
cb(request, response) // invocation time
}
In the case of your example, it's just up to node to pass your function request and response whenever .get is invoked.
The whole point of the callback is that the invoked function calls it back.
In the case of router.get, it will insert the route (path, method, callback) in a lookup table; when a request comes in, Express will construct the response object, match the request's path and method against all the entries in the lookup table, take the callback from the matching entry and invoke callback(request, response) (passing the detected request and created response).
They get populated by whatever code is calling the callback. In your example, this is something inside the Express framework, though Express uses the node http library under the hood and adds additional functionality to the request and response objects provided by it.
But in code you write you can create a callback function signature that takes whatever params you want.

How to pass in a variable to a .then() callback function from an outer scope?

I have an API receiving an request and doing some querys and validation.
I want to use the response reference from the route inside the findUserPlayer function so I can send something to the client. The findUser function will return a data object that will be used on findUserPlayer.
var api = express.Router();
api.post('/signup', function (request, response) {
UserModel.find(req.body)
.then(findUser, createUser)
.then(findUserPlayer, createUserPlayer);
});
var findUserPlayer = function (data, res) {
//...
res.json(object);
};
I've tried calling findUserPlayer(data, res), which gives me 'data is not defined'.
I've tried calling findUserPlayer(res), which will override data.
How can I use the response object inside that callback?
Instead of directly passing findUserPlayer function as a success handler, you can define a success handler function while will then call findUserPlayer.
var api = express.Router();
api.post('/signup', function (request, response) {
UserModel.find(req.body)
.then(findUser, createUser)
.then(function(data) {
return findUserPlayer(data, response);
}, createUserPlayer);
});
var findUserPlayer = function (data, res) {
//...
res.json(object);
};
JavaScript is a very flexible language which means there are many ways you can handle this, one of the easiest (in terms of minimum code change) is to reverse the order of arguments in findUserPlayer and binding your context (.bind(response)).
But that would be a poor design choice. There's no reason for a function that "finds a user" to deal with responses or json. It's out of this functions scope and responsibility. The request handler is the one that should deal with formatting a relevant response, and I'd do that by returning the relevant data in the promise chain and eventually:
.then(function(data) {
response.json(data);
});
I'm a big fan of lodash and sometimes to a fault, but thought I would add the following using lodash's partialRight function.
var _ = require('lodash');
...
UserModel.find(req.body)
.then(findUser, createUser)
.then(_.partialRight(findUserPlayer, response), createUserPlayer);
_.partialRight returns a new function with the partials appended to the new function. The first argument of _.partialRight is the function we want to append the arguments to. The subsequent arguments are the args we want to append to the function.
I'm assuming the following function signature: findUserPlayer(data, response). _.partialRight appends the response object to the new function. The new function signature looks like this now: function (data).
documentation

Function parameters out of nowhere?

I've just begun to work with NodeJS and I find myself puzzled on code such as
app.get('/home', function(req, res) {
// req and res are objects
})
I often see these kinds of function calls where the parameters in the anonymous function seem to come out of nowhere, yet contain various attributes and/or methods within?
You are passing a function to another function, this
function(req, res) {
}
is a function. Assuming you gave it a local variable name like b in the called method, the function could then be invoked. As an example, -
app.get = function(a, b) { // <-- assign a function to app.get
b("one", "two"); // <-- and then req would be one, and res would be two.
}
This is actually found here:
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
As you can see, express() is this and it is being used as a parameter to createServer.
You can find the documentation of createServer here:
The requestListener is a function which is automatically added to the 'request' event.
Then when you check the request event here:
Event: 'request'
function (request, response) { }
Emitted each time there is a request. Note that there may be multiple
requests per connection (in the case of keep-alive connections).
request is an instance of http.IncomingMessage and response is an
instance of http.ServerResponse.
Technically this event gets emitted every time a new request from a browser is received.
And this code
app.get('/home', function(req, res) {
// req and res are objects
})
Is somewhat a listener for a request to this route (check expressjs source code).
So req and res are short-hand of request and response and are passed from the request event.
Then express added some more methods/properties found here and here.
If you want to see the code for .get(), see here.

What are the 'req' and 'res' parameters in node and node middleware?

I'm new to Node and Express and the other layers that go along with building web apps with node and the request and response parameters are really confusing me. My confusion lies in the fact that those two parameters are often present in a function but oftentimes one or both of them isn't declared. Also, much of the time an additional parameter will be thrown in, like 'next' or something else. For example, I have the following router for an API:
router.route('/teams')
// create a team at POST http://localhost:8080/api/teams
.post(function(req, res) {
var team = new Team();
team.name = req.body.name;
team.location = req.body.location;
// save the new team and check for errors
team.save(function(err) {
if (err) {
res.send(err);
};
res.json({ message: 'Team created!' });
});
})
// GET all the teams at GET http://localhost:8080/api/teams
.get(function(req, res) {
Team.find(function(err, teams){
if (err) {
res.send(err);
};
res.json(teams);
});
});
Both .post and .get call a function with req and res as parameters, but req is never used. So how does the function know what to do with req or res if they're not defined and used or not used in completely different orders? Or if I named them something completely different?
What exactly is happening with requests and responses? Sorry for my ignorance. I've read the documentation but it's not clicking.
Thanks.
When you use expressApp.use('/some/route', myRouteHandler); Express will listen for requests for that route, and when it's hit, it will call the function you provided (callback). It will give it three parameters: request and response, and next. (Actually could be four, but lets keep things simple.)
So, your callback might be defined like this:
function myRouteHandler(a, b, c) {
// do stuff
};
or like this:
function myRouteHandler(req, res, next) {
// stuff
}
or simply:
function myRouteHandler() {
// stuff
}
Whatever you do, doesn't matter. When the app is started, express listens for requests.
When one of them matches the route (/some/route), express will, in its internal workings, call the function you provided, like this:
myRouteHandler(requestObject, responseObject, nextMiddleware);
So in the first case, you can access the request (like, request headers, full url, caller IP address or similar) by using req. In your second case, you'll access it by calling a. In the third case, you can use arguments[0].
By convention, people will use the form: myCallback(req, res) and know that Express will put the request object as the first param, and response as the second. The response object actually has a method end(), so you can end the request. If there is also a next() object, you can call the next middleware.
Say you have a route defined like this:
app.use('/api/users', checkAuthorizationHandler);
app.use('/api/users', makeSureTheIPisFromOurInternalNetwork);
app.use('/api/users', nowHandleTheResponse);
Each of those handlers gets a third param. If you name it, you'd usually in your function declaration call it 'next' parameter. It means, the next function in order.
Say your function checkAuthorizationHandler(req, res, next) will check for req.headers('auth') token and if it's ok, it will in the function body, call next().
Then the function makeSureTheIPisFromOurInternalNetwork(a, b, c) is called. It will check that the a.ip is a LAN ip address and call c();
Finally your function nowHandleTheResponse() will find all users, and respond with a JSON object of the users: arguments[1].json([user1, user2, user3]);
So, first param is something that express gives you, it's the request, second is response, third is a next middleware function in line. No matter what you call them, they are there.
P.S. You can also declare your middleware with four params:
function(error, req, res, next);
Express will actually check your function and if it finds that you have four params and not two or three, it will give you any errors thrown by the middleware that ran earlier in the chain. Meaning, if your checkAuthHandler says next(new Error('Not authorized'));, your next function might check for that error, and if it's present, not give results. Often however will the middleware which detects errors just res.end('some error message');
If I haven't confused you enough, just say, I've got more where this came from :)
It is the framework convention. The first argument is the request, the second is the response. If you're declaring a middleware (.use), the third argument is the next middleware in the chain.
You can name these variables however you want, as long as you know the order. You could have something like: .post(function(a,b) {}); and then the request is represented by variable a, and response by variable b.
If, for whatever reason, you don't need the request, only the response, you still have to have a first argument, as the response is represented by the second argument.
In javascript, there's no method overload like in Java, for example (maybe here's where you getting the confusion from). A function is represented by its name, not how many arguments it takes. Here's a simple example:
function logToConsole(level, message) {
if (!message) {
message = level;
level = 'INFO';
}
console.log('['+level+']', message);
}
logToConsole('My message'); // prints out: "[INFO] My message"
logToConsole('WARN', 'My message'); // prints out: "[WARN] My message"
Did you notice how we defined a default value for level, based on the existence of message?
Hope this clarifies things a bit.
Request, response and next are passed to all middleware functions. The request object contains information about the HTTP request, and the response object is used to handle the request. The Expressjs documentation details these objects. The next() call is used in something called the dispatcher, a middleware function may or may not call next() depending on usage. Next simply calls the following middleware.
Here is an example of using next():
function helloWorld(req,res,next){
console.log('Hello, world!');
next();
}
// This function doesn't call next(), therefore it will
// not call the subsequent middleware in the dispatcher
function goodbyeWorld(req,res,next){
console.log('Goodbye, world!');
}
app.use(helloWorld);
app.use(goodbyeWorld);
Output:
Hello, world!
Goodbye, world!
Now let's reorder the middleware
app.use(goodbyeWorld);
app.use(helloWorld);
Output:
Goodbye, world!
The helloWorld function is not called. Notice the importance of middleware order and the next() function call.

Trouble understanding Node.js callbacks

Today is my first foray into nodejs and I am particularly stumped trying to understand the way the following piece of logic flows. The logic is as follows:
request({ uri: db.createDbQuery('identifier:abcd1234') },
function(err, response, body) {
response.should.have.status(200);
var search = JSON.parse(body);
search.response.numFound.should.equal(1);
done();
});
});
At a higher level I do understand is that an http request is being made and the function is being called at some juncture that is taking the response and doing something to it. What I am trying to understand is the proper order of the calls and how does the binding of variables take place in the above given logic. How does the compiler know how to bind the return values from the request to the anonymous function? Basically, I want to gain an understanding on how things work under the hood for this snippet.
Thanks
Your question isnt specific to node.js, this is basically a feature of javascript.
Basically you are calling request() which is defined like function request(obj, callback)
Internally, the http request is being called, and once its completed, it calls callback which is actually a function pointer.
function request(obj, callback){
//http request logic...
var err = request_logic_internal_function();
var response = ...
var body = ...
callback(err, response, body)
}
Your code can actually be restructured as :
var options = { uri: db.createDbQuery('identifier:abcd1234') };
var request_callback = function(err, response, body) {
response.should.have.status(200);
var search = JSON.parse(body);
search.response.numFound.should.equal(1);
done();
};
request(options, request_callback);
What you're basically doing is sending in a function pointer as a variable.
I don't know what library(ies) you're using, and it looks like you may have anonymized them by assigning methods into your code's global scope like request, done, and db.
What I can say is this:
That indentation is horrible and initially misled me on what it was doing, please gg=G (vim syntax) your code so it's properly indented.
request takes two arguments, a configuration object and a callback.
db.createDbQuery must be a blocking method or the anonymous object you're creating won't have the proper value.
request uses that configuration value, makes a non-blocking I/O request of some kind, and later will call the callback function you provide. That means that the code immediately after that request call will execute before the callback you provide will execute.
Some time later the request data will come back, Node.js's event loop will provide the data to the library's registered event handler (which may or may not be your callback directly -- it could do something to it and then call your event handler afterwards, you don't know or really care).
Then the function does some checks that will throw errors if they fail, and finally calls a done function in its scope (defined somewhere else) that will execute and continue the logical stream of execution.

Categories