NodeJS http.get with state object in the response - node.js

I am struggeling with something that I belive supposed to be quite simple once you know how to do it , I apologize if its already been answered - I have searched throughly and could not find an answer.
In Node JS , I want to perform http.get , in the response parameter, I dont pass a closure but a reference to a function that receive a response in a parameter (that way I can have re usability) but I also want to have a state/data object that will be passed to this response function so I could further handle the transaction - with closures its easy but then I need to copy/paste all the time.
https.get({
host: 'www.****.com',
path: ********
}, this._searchResponseHandler.bind(this));
How can that pleased be achieved ?
Thank you ,
James

You can use bind() to also provide initial arguments to your function (the result of which are called partial functions):
this._searchResponseHandler.bind(this, stateObj)
The signature of the handler would become:
_searchResponseHandler : function(stateObj, res) { ... }

Related

How to read nodejs documentation regarding callback parameters (node v8.x)

I am trying to understand the node.js documentation specifically for the https.get() method. https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_get_options_callback
What is unclear to me is the callback. The example in the document indicates the callback can take a res (response) object as its parameter but I am unsure if this is the only parameter it can take or more importantly where I can find the definition of the res object so I can know what properties and methods I can access on this object.
Is there a straightforward way to identify this?
I have read this thread: Trying to understand nodejs documentation. How to discover callback parameters and the answers seem to suggest that if there is a non-error argument that a callback can take it will be documented, but I am assuming that answer is outdated.
I've run into the same issue with many Node/NPM packages. Documentation sometimes does not describe the parameters well.
So, welcome to JavaScript in 2018! It's gotten a lot better, though, to be honest.
My go-to method is to try the methods and dump the information myself.
Try a console.dir(res) in your callback:
https.get('https://encrypted.google.com/', (res) => {
console.dir(res);
});
Alternatively, you can set a breakpoint in the callback and inspect it yourself. You can then probe the arguments object* to see what else, if anything, was passed as an argument, or do another console dump:
https.get('https://encrypted.google.com/', function (res) {
console.dir("args:", arguments);
console.dir("res:", res);
});
EDIT: Wait, apparently the arguments variable is not available to arrow functions, fixed the second example.
*From MDN:
The arguments object is not an Array. It is similar to an Array, but
does not have any Array properties except length.
From your link https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_get_options_callback, you can see that it works like the http version :
Like http.get() but for HTTPS.
With http.get() clickable.
On that page (https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_http_get_options_callback), we can see this :
The callback is invoked with a single argument that is an instance of http.IncomingMessage
With http.IncomingMessage clickable, linking this page :
https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_class_http_incomingmessage
I agree the Node documentation is not very clear about the callbacks in general, and that is a shame. You can still use IDEs with good intellisense (and JSDoc to identify the type of the function parameters), like VSCode.
Or you can use a debugger, always works :)
Edit: If you want to see all the parameters sent to a function, you can use the spread syntax like this :
function foo(...params) {
// Here params is an array containing all the parameters that were sent to the function
}
If you want the absolute truth, you can look at the implementation. Though that's fairly time consuming.
If you find that the documentation is wrong, or in this case could be improved by adding a sentence about the callback parameter to https.get(), please open an issue, or, better yet, a pull request. This is where the change needs to be made:
https://github.com/nodejs/node/blob/67790962daccb5ff19c977119d7231cbe175c206/doc/api/https.md

Access current req object everywhere in Node.js Express

I wonder how to access req object if there's no 'req' parameter in callback.
This is the scenarioļ¼š
In ExpressJs, I have a common function, it uses to handle something with 'req' object, but not pass req into it.
module.exports = {
get: function(){
var req = global.currentRequest;
//do something...
}
}
My current solution is that I write a middleware for all request, I put the 'req' in global variable, then I can access the 'req' everywhere with 'global.currentRequest'.
// in app.js
app.use(function (req, res, next) {
global.currentRequest= req;
next();
});
But I don't know if it's good? Can anyone have suggestions?
Thanks a lot!
The only proper way is to pass the req object through as an argument to all functions that need it.
Stashing it in a global simply will not work because multiple requests can be in process at the same time if any requests use async calls as part of their processing and those multiple requests will stomp on each other making a hard to track down bug. There are no shortcuts here. Pass the current request as an argument to any code that needs it.
You cannot put request-specific data into a global in node.js, ever. Doing so will create an opportunity for two requests that are in-flight at the same time to stomp on each other and for data to get confused between requests. Remember, this is a server that is potentially handling requests for many clients. You cannot use synchronous, one-at-a-time thinking for a server. A node.js server may potentially have many requests all in flight at the same time and thus plain globals cannot be used for request-specific data.
There is no shortcut here. You will just have to pass the req object through to the function that needs it. If that means you have to change the function signature of several intervening functions, then so-be-it. That's what you have to do. That is the only correct way to solve this type of problem.
There are some circumstances where you may be able to use a closure to "capture" the desired req object and then use it in inner functions without passing it to those inner functions, but it does not sound like that is your function structure. We'd have to see a lot more of your real/actual code to be able to know whether that's a possibility or not.
Actually, this is possible with something like global-request-context
This is using zone.js which let you persist variables across async tasks.

NodeJs: Socket.io use() method

I can't find any document that make an understanding about use() method. Please explane socket.use() method.
Thanks a lot
socket.use() is basically where you can add middleware functions, which just means that the function passed as the parameter for thesocket.use() function is executed for every piece of info received.
Here's the socket.io docs
https://socket.io/docs/server-api/#socket-use-fn
socketio.use() method is same like as express_app.use() method , means both are used for passing middleware-functions , where middleware-functions can control/manipulate every upcoming requests/response on the server.

nodeJS callback error parameter

I'm learning node now and I'm confused about the err parameter.
I thought it's supposed to be the first argument of a callback function but I don't see it in many call back functions. Can anyone explain it to me? Thanks!
There's many different kinds of functions and callback functions in particular. The Node.js standard for callback functions is those of the form:
function(err, arg1, arg2, ...)
Where arg1 and so forth are only present if relevant but the err argument is always first. This is the reverse of a lot of historical JavaScript code where errors would be the last argument.
The Node.js method of forcing the error as the first argument even if there's no error makes ignoring errors harder, you rarely forget to declare that argument, and makes their location predictable.
Now this only applies in the case of a general-purpose callback. That is, there are occasions where calling a function will trigger a singular callback at some point in the future. You'll see them used like this:
doStuff(function(err, successValue) { ... });
There's also the style popularized by jQuery where one or more of your callbacks will be triggered depending on the outcome of the operation:
doStuff({
success: function(successValue) { ... },
error: function(err) { ... },
timeout: function() { ... }
});
Note that in this case you may have both the error and timeout callbacks being fired. You're not obligated to populate all of these, either.
The downside to this approach is the unpredictability of which ones get called and the risk of handling something twice inadvertently.
The error parameter is usually for asynchronous code.
node errors
Most asynchronous methods that accept a callback function will accept an Error object passed as the first argument to that function. If that first argument is not null and is an instance of Error, then an error occurred that should be handled.
app.get() sends get request and return an error like a 404
and you could do something like this res.status(404).render( in app.get()
Express error handling
error-handling functions have four arguments instead of three: (err, req, res, next)
The reason why some code uses err as the first parameter is because some code like fs.readFileis programmed to check if there was an error and to handle it. The author of the API specifically wrote code to check the first argument for an error and handle it.
That's why it is available to you for some methods an unavailable for other methods.
First: a callback is just a function. Different callbacks serve different purposes.
In general, a function that performs an asynchronous action and should "return" a value gets passed a callback function that will take (at least) two arguments: the first is used to pass errors (if any), the second (and following) are used to pass the value(s) that should be returned to the caller.
You noticed that net.createServer() will also take a callback function, but that function only has one argument.
That's because, in this case, the callback isn't used to pass errors and/or values. Instead, it's a function that gets called when a new connection is made to the server.
It's really a bit of a shortcut. This code:
var server = net.createServer(function(connection) {
...
});
Is short for this code:
var server = net.createServer();
server.on('connection', function(connection) {
...
});

node.js middleware and js encapsulation

I'm new to javascript, and jumped right into node.js. I've read a lot of theory, and began well with the practical side (I'm writing an API for a mobile app), but I have one basic problem, which has lead me to middleware. I've successfully implemented a middleware function, but I would like to know if the use I'm giving the idea of middleware is OK, and also resolve the original problem which brought me to middleware. My question is two-fold, it's as follows:
1) From what I could gather, the idea of using middleware is repeating a process before actually processing the request. I've used it for token verification, as follows:
Only one of my urls doesn't receive a token parameter, so
app.js
app.get('/settings', auth.validateToken, auth.settings);
auth.js
function validateToken(req, res, next){ //code };
In validateToken, my code checks the token, then calls next() if everything is OK, or modifies res as json to return a specific error code.
My questions regarding this are: a) Is this a correct use of middleware? b) is there a [correct] way of passing a value onto the next function? Instead of calling next only if everything is OK, is there a [correct] way of calling next either way, and knowing from inside the next function (whichever it is), if the middleware was succesful or not? If there is, would this be a proper use of middleware? This precise point brings me to my original problem, and part two of this question, which is encapsulating functions:
THIS PART WAS FIXED, SEE MY SECOND COMMENT.
2) I discovered middleware trying to simply encapsulate validateToken, and be able to call it from inside the functions that the get handlers point to, for example auth.settings.
I'm used to common, sequential programming, and not in javascript, and haven't for the life of me been able to understand how to do this, taking into account the event-based nature of node.js.
What I want to do right now is write a function which simply verifies the user and password. I have it perfectly written inside a particular handler, but was about to copy-paste it to another one, so I stopped. I want to do things the right way from scratch, and understand node.js. One of the specific problems I've been having, is that the error code I have to return when user and password don't match are different depending on the parent function, so I would need this function to be able to tell the callback function "hey, the password and user don't match", so from the parent function I can respond with the correct message.
I think what I actually want is to write an asynchronous function I can call from inside another one.
I hope I've been clear, I've been trying to solve this on my own, but I can't quite finish wrapping my head around what my actual problem is, I'm guessing it's due to my recent introduction to node.js and JS.
Thanks in advance! Jennifer.
1) There is res.locals object (http://expressjs.com/api.html#res.locals) designed to store data local to the request and to pass them from one middleware to another. After request is processed this object is disposed of. If you want to store data within the session you can use req.session.
2) If I understand your question, you want a function asynchronously passing the response to the caller. You can do it in the same way most node's functions are designed.
You define a function in this way:
function doSomething(parameters, callback) {
// ... do something
// if (errorConddition()) err = errorCode();
if (callback) callback(err, result)
}
And the caller instead of using the return value of the function passes callback to this function:
function caller(req, res, next) {
//...
doSomething(params, function(err, result) {
if (! err && result) {
// do something with the result
next();
} else {
// do something else
next();
// or even res.redirect('/error');
}
});
}
If you find yourself writing similar callback functions you should define them as function and just pass the function as parameter:
//...
doSomething(param, processIt);
function processIt(err, result) {
// ...
}
What keeps you confused, probably, is that you don't treat functions as values yet, which is a very specific to JavaScript (not counting for languages that are little used).
In validateToken, my code checks the token, then calls next() if everything is OK, or modifies res as json to return a specific error code.
a) Is this a correct use of middleware?
b) is there a [correct] way of passing a value onto the next function?
Yes that is the correct way of using middleware, although depending on the response message type and specifications you could use the built in error handling of connect. That is in this example generate a 401 status code by calling next({status:401,stack:'Unauthorized'});
The middleware system is designed to handle the request by going through a series of functions until one function replies to the request. This is why the next function only takes one argument which is error
-> if an error object is passed to the next function then it will be used to create a response and no further middleware will be processed. The manner in which error response is created is as follows
// default to 500
if (res.statusCode < 400) res.statusCode = 500;
debug('default %s', res.statusCode);
// respect err.status
if (err.status) res.statusCode = err.status;
// production gets a basic error message
var msg = 'production' == env
? http.STATUS_CODES[res.statusCode]
: err.stack || err.toString();
-> to pass values down the middleware stack modifying the request object is the best method. This ensures that all processing is bound to that specific request and since the request object goes through every middleware function it is a good way to pass information down the stack.

Resources