In Node JS how to pass a variable to http.request callback? - javascript

I call http.request().end() and I need to pass a variable to the callback function.
How do I do this?
For my situation, a user accesses the server, the server sends an HTTP request to our API, and then the server needs to respond to that user with information returned from the HTTP request. I can't figure out a way to do that without using a global variable, which would be an issue, since if 2 people were to do this at once, both messages would be sent to the same user
Not sure how it would help but here's kind what I'm trying to do..
callback = function(response){
//...
respondToUser(userId);
}
function doStuff(userId){
http.request({host:'www.google.com'}, callback).end();
}

It is called a "closure" where you are keeping the context with the function you are writing, like this
function doStuff(userId){
var callback = function(response){
//...
respondToUser(userId);
}
http.request({host:'www.google.com'}, callback).end();
}

Related

Socket.io passing callback functions

I am perplexed as to what is happening in this scenario
Client:
socket.emit('ferret', 'tobi', function (data) {
console.log(data); // data will be 'woot'
});
Server:
io.on('connection', function (socket) {
socket.on('ferret', function (name, fn) {
fn('woot');
});
});
This is from the docs. How does it make any sense that a function is being passed to the server for the callback? How can the server be calling a client function? I am very confused.
It's obvious that you can't directly call a function on the client from the server.
You can easily do this indirectly, though:
When the client sends the ferret message, it stores the given function locally with an ID.
The client sends this ID along with the message to the server.
When the server wants to call the client function, it sends a special message back with the ID and the arguments to the function.
When the client recieves this special message, it can look up the function by its ID and call it.
I do not know if this is exactly what Socket.io does, but it's reasonable to assume that it's something similar to this.
Edit: Looking at the source code (here and here), this does indeed seem to be pretty much what Socket.io does.
The third argument to the emit method accepts a callback that will be passed to the server so that you can call in acknowledgement with any data you wish. It's actually really convenient and saves the effort of having paired call-response events.
Acknowledge is the way to get a response corresponding to a sent message. The following is a code snippet for server-side.
io.sockets.on('connection', function(socket) {
socket.on('echo', function(data, callback) {
callback(data);
});
});

Why modify request after request.post

Newbie question while trying to understand code created by others. Believe me I tried to understand this. Here goes..
For what reason would someone still call functions like .qs() and .json() in Request - module after we got what we need with .post() and sent the response already. They can't affect the request.post as they are called afterwards, can they?
With my skills I'm not able to understand from response module API docs (v2.22.0) what these actually do.
This is not the whole code but I tried to get the important parts here:
// When request comes to /getthisapge, make external query and return data in JSON format.
var request = require('request');
module.exports = function(app) {
app.get('/getthispage', function(req, res, next) {
var filter = {};
var query = {};
filter.category = req.query.category;
query.onBehalf = req.query.onBehalf;
request.post(URIandoptions, function(error, response, body) {
res.json(body.members)
}).qs(query).json(filter);
}
}
Without knowing exactly what the post function does (unnecessary to your question), you need to look at the order of execution.
request.post(URIandoptions, function (error, response, body){
res.json(body.members)
})
.qs(query) // ?
.json(filter); // ?
The function passed into post() does not get called at that specific moment. It is given to the post() function to do with as it pleases. This means technically that the function may never be called (depends on the api).
qs() and json() both get called upon the returning of the prior function. Usually this type of api means the following:
call post(), passing in a function to be run on completion
call qs() to setup the query details
call json() to tell the post function how to act, which in turn executes the actual post, running the completion function after data has been retrieved.

So about requesting in node.js

Ok look at this code..
var http = require('http');
var handleRequest = function (request, response){
response.writeHead(200,{"context-type":"text/plain"});
response.end('Welcome to the node club! :)');
}
//the createServer method... creates a server WOW!
http.createServer(handleRequest).listen(8888);
console.log('The servers are running and the bacon is stopping');
It seems simple enough, the handleRequest function will create a writeHead function when the node will allow me to respond ...right? And if that is the case, I will be able to write out "Welcome to the node club" in the end method. The thing I don't understand about node is the request variable or object or whatever. In the function am I requesting the node? Or is the node requesting me to run a function? I'm not using the request variable in the function so would it still run if I left it out?
The argument to http.createServer is a function to be called on each request. The function is documented as
function (request, response) { }
request is an instance of http.IncomingMessage and response is an instance of http.ServerResponse.
What you do in this function is up to you; it can be anything.
However, virtually all web applications end up writing an answer to the client, and that's done via the response object. Also, since an application that serves just one page is quite limited, most applications also want to get information from the HTTP request, including the path requested (something like '/questions/37265770/so-about-requesting-in-node-js', in request.path), HTTP POST parameters and the like.
Your function gets called with two arguments, the first of which is the request object, the second the response object. There is no magic involved - you seem to call magic "node", but that's just the name of the project.

Meteor method returns undefined to the client (asynchronous)

I've been working on integrating Google Recaptcha into a Meteor and AngularJS web application. Everything was smooth sailing until I had to validate the recaptcha response -- for some bizarre reason, I can't get an async response from the backend to the frontend.
I've tried a lot of different variations and have read many, many posts on SO and the internet in general, but with no luck -- so I opted to post my own question.
Here's what I'm doing:
Client:
Meteor.call('recaptcha.methods.validateRecaptcha', { 'response' : this.recaptcha.getResponse(this.id) }, function(error, result) {
// error and result are both undefined
console.log('Do something with the ' + error + ' or ' + result + '.');
}
So, I'm calling a Meteor method and passing in a callback that is run when the method is done. However, the error and result parameters are both undefined.
Server:
run: function(data) {
if (this.isSimulation) {
/*
* Client-side simulations won't have access to any of the
* Meteor.settings.private variables, so we should just stop here.
*/
return;
}
return Meteor.wrapAsync(HTTP.post)(_someUrl, _someOptions);
}
That last line is a shortened version of the sync/async structure that I've found in several Meteor guides (I also tried this version), namely:
var syncFunc = Meteor.wrapAsync(HTTP.post);
var result = syncFunc(Meteor.settings.private.grecaptcha.verifyUrl, _options);
return result;
I've also tried a version using Futures:
var Future = Npm.require( 'fibers/future' );
var future = new Future();
var callback = future.resolver();
HTTP.post(Meteor.settings.private.grecaptcha.verifyUrl, _options, callback);
return future.wait();
Now, the intention here is that I use Meteor.call() to call this method from the client, the client-side stub runs (to prevent simulation errors since we use private Meteor.settings variables in the real non-SO server-side code) and returns immediately (which happens), and the server hits Google's Recaptcha API (which happens and the server receives a response) before returning the result to the client (which doesn't happen -- the callback occurs but with no error/success data).
My thought is that one of two things are happening:
I'm just doing something wrong and I'm not properly sending the data back to the client.
The synchronous client stub (which returns immediately) is telling the client that the server response isn't important, so it never waits for the proper asynchronous response.
Could any of the Meteor gurus weigh in here and let me know what's going on and how to get async requests to play nicely in a Meteor application?
Thanks!
From the documentation for HTTP.call, which is the generic version of HTTP.post, it says
Optional callback. If passed, the method runs asynchronously, instead of synchronously, and calls asyncCallback. On the client, this callback is required.
So, on server, you can run it asynchronously like this
run: function(data) {
if (this.isSimulation) {
/*
* Client-side simulations won't have access to any of the
* Meteor.settings.private variables, so we should just stop here.
*/
return;
}
// No need to pass callback on server.
// Since this part is not executed on client, you can do this
// Or you can use Meteor.isClient to run it asynchronously when the call is from client.
return HTTP.post(Meteor.settings.private.grecaptcha.verifyUrl, _options);
}

SocketIO callback from client to server doesn't work (null object instead)

I'm facing a weird problem with SocketIO, on the server-side i emit() this :
$s.sockets.emit(scope, {some: datas},
function(feedback) {
console.log('received callback');
}
);
And on the client-side I do this :
this.Socket.on(handler, function (datas, callback) {
callback('test');
}
I'm waiting for the client to send a callback('test') the server will receive. Then it would output a simple console.log('received callback')
The client effectively receive the server request but on the client-side the callback type is null (object) instead of function ... If I remove the function() on the server side and don't wait for a callback the type on the client-side will be undefined which means that when the server expect a callback the function is somehow transmitted but transformed in an object (?)
Is it a bug ? Am I doing something wrong here ? Really weird ...
One more detail : i'm currently using SocketIO 0.9.16
Thanks people ;)
Ok I didn't find any solution on getting a callback through emit() functionality. So I made a "trick" which is a parallel working solution :
When I emit() something that will involve a callback() on the server-side, I generate a key through a function and send the datas adding a { callback : key } at the end of my datas object.
I also generate a socket.on(key, function(datas) { callback(datas); socket.removeListener(key); } which will be an equivalent of a classic callback in the system at the end.
This will be understood by the front which will emit(key, datas...) in response. The server will receive everything, do the stuff, and remove the listener.
Works like a charm but a bit complicated to make at first. Would've been nice if it worked directly with SocketIO ...
If someone got stuck, I hope this helps :)

Categories

Resources