Using Node.js and Express:
When I call the Application.listen method, I can access the returned Server object by name inside the callback function I pass as an argument to the Application.listen method.
var myVariableName = app.listen(3000, () => {
console.log(myVariableName.address().port)
});
I can already call methods on myVariableName even though I'm in the act of creating/assigning to that variable!
How is this possible? I want to understand so I can implement functions that allow me to reference returned object by name in a callback argument.
As specified in comment by certainperformance, you can not get that variable. Instead you can use another event as,
app.listen(3000)
app.on('listening', () =>{
console.log(app.address().port)
})
Related
I am creating a middleware for adding trace id to each req and come across async hook and async localstorage, but I am confused about why next function is passed inside the run method, and when I remove the next function and move it outside the run function the middleware does not work as expected so can someone please explain to me what does putting next() inside run() is doing to make things work. Below is the code sample-
app.use((req, res, next) => {
asyncLocalStorage.run(new Map(), () => {
asyncLocalStorage.getStore().set("requestId", uuid());
next();
});
});
If you place next() outside the callback, it will not be run within the context created by asyncLocalStorage and (hence) you won't be able to access the store.
This is also explained in the documentation:
The store is not accessible outside of the callback function. The store is accessible to any asynchronous operations created within the callback.
When I declare a variable inside of one of my functions I am not able to call on it outside of that function.
async function submitCardInfo () {
try {
const example1 = 'testing';
let example2 = 'testing2';
} catch (error) {
setRunningError('Error Submitting Card Credentials')
console.log(error)
}
console.log(example1);
this is my function to submit Card info and I declare a couple of variables at the bottom. When I call on those variables later in my code(outside of the function submitCardInfo) they aren't defined. That console.log example will say that example1 is undefined.
EDIT BELOW
async function submitCardInfo () {
try {
data = {
example1:'testing',
example2:'testing2',
} catch (error) {
setRunningError('Error Submitting Card Credentials')
console.log(error)
} await submitCardInfo()
console.log(example1);
Ok when I run a similar code to this I still get undefined. Can you please try and example using this example and explain how you would do it.
SOLUTION Below -
Hello what I do now is use class and this.(variable) and I am able to change the value of the variable and use it anywhere in my code. Another way is to declare a variable using var outside of the local scope and then you are able to use that variable other places in your code.
Variables in Javascript are only accessible within the function that they are declared in. And, each time you call the function, it creates a new and different variable in that function. This is referred to as "function scoping". If you declare the variable with const or let (instead of var), then the variable is only available within the block that it is declared in. This is referred as "block scoping".
There is a "global scope" where variables can be accessible anywhere, but this is nearly always discouraged for a variety of reasons. And, calling a function that changes a global value as its function is referred to as "side effect" programming and is also discouraged.
If you want to call the function and communicate the value of that variable back to the outside world (outside the function), then you can return it from the function where the caller can use the return value.
If you want to return more than one value, then you can put them in an object or an array and return the object or the array as the single return value.
If the function is async, then all async functions return a promise and the returned value inside the async function becomes the resolved value of the promise that is returned. The caller would use await or .then() to get the resolved value of the promise.
In your specific function example, you should not that async functions would generally only be used if you had asynchronous operations inside the function and thus were interested in using await inside the function. If you have no asynchronous operations, then it is simpler to code the function as a regular function (without the async keyword) and then you can just directly return a value and the caller can directly receive the return value.
Thats happening because variables have diferrence scopes. Function and global scope, let and const also have another scope which is block scope, that means that if you declared it inside curly braces {} (Ej: your try, catch block, a function, etc.) they will only live there. Thats why you can't access them from ouside of any other part of your code. The only way you can access a variable from any part of your file is that if you declare it in the global scope
I am reviewing a sample nodejs server code, which is working fine. but could not understand the following code:
var handlers = {};
// Creating a sample handler
handlers.sample = function(data,callback){
callback(406,{'name':'sample handler'}); // How is this line of code working??
};
// Creating a not found handler
handlers.notFound = function(data,callback){
callback(404); // How is this line of code working??
};
In the entire code there is no implementation of "callback" function then how
callback(406,{'name':'sample handler'});
and
callback(404);
are working?
Please suggest. Thanks.
callback isn't implemented in the code you posted; it's a named parameter.
To call one of the functions that requires a callback, you'll need to pass it in as an argument, like:
handlers.sample("some data", () => console.log("I'm in a callback!));
The first argument ("some data") goes in the data parameter, and the second argument (() => console.log("I'm in a callback!)) goes in the callback parameter. When callback(404) is run, it executes the callback function (in the above example, it would do console.log("I'm in a callback!)).
Basically, when you call handlers.sample, you should pass a function as your second argument, and that function will be called, usually asynchronously, and presumably after something is done with the data you pass as the first argument. For example, based on the code you provided:
handlers.sample(dataObject, (number, object) => {
console.log(number)
console.log(object.name)
})
would yield this result in the console:
406
sample handler
I’m curious if this is a public library you are seeing this code in, so we can take a closer look?
I did a further digging in into this and found that
selectedHandler
in the following code (this is not mentioned in the question) is getting resolved into handlers.sample or handlers.notFound variable names based on some logic (which is not mentioned here)
selectedHandler(data,function(status,payloadData){
// somelogic with the status and payloadData
});
And second parameter of this function which is a complete function in itself
function(status,payloadData){
// somelogic with the status and payloadData
}
is going as the second parameter in handlers.sample or handlers.notFound which is a Callback. So execution of Callback in the current context is execution of this function (this function is anonymous because it has no name and getting executed as Callback)
When I receive the 'catch' callback, 'this' is undefined, even using arrow funcitions. Any ideas?
private all(req: Request, res: Response): void {
EntityRepository.getRepositoty(req.params.etName).then(repo => {
...
}).catch((err) => {
this.handleError(res, err); // here I get undefined.
});
}
how the all func is called.
It's called based on a Express route.
Added mathod bind as #jfriend00 suggested.
constructor() {
// Connect to database.
DataAccess.connect();
// Starts configuring routes for api
this.router = Router();
// Bad request due to absence of entity type.
this.router.get("/", (req, res) => {
res.statusCode = 400;
res.statusMessage = SysMsgs.error.noEntityTypeSpecified.message;
res.send();
});
// Added method 'bind'.
this.router.get(this.routeBase, this.all.bind(this));
this.router.get(this.routeBase + "/:id", this.findOne.bind(this));
}
With arrow functions, this will retain the value it had in the scope prior to the arrow function call. In your case, that means it will have whatever value this was at the beginning of your all function. So, that value of this depends upon how the all function is called.
And, based on your this.router.get() where you specify this.all as the callback, that means that this inside of all will be set to whatever Express sets it to when it calls that callback. And, that is undefined.
You can fix your issue by using .bind().
this.router.get(this.routeBase, this.all.bind(this));
That will assure that the appropriate this is set when .all() runs. And, then your arrow function inside of all() will use that value of this.
Note: you will need to use .bind() for any method you are passing as a callback where you expect this to be the object inside the callback. When you pass something like this.all, the value of this is lost and only a reference to the method is passed. The caller then calls that method as a normal function with no object binding. You use .bind() to take control of that yourself. .bind() essentially creates a little stub function that reattaches the appropriate this pointer by calling your method using it.
You could also make your own wrapper arrow function for it:
this.router.get(this.routeBase, (req, res) => this.all(req, res));
which as Saravana points out will retain TypeScript type checking.
While #jfriend00's answer covers the problem with your code and there is nothing wrong with using bind in JavaScript, there is one little problem when you use bind in TypeScript though. The type signature for bind is:
bind(this: Function, thisArg: any, ...argArray: any[]): any;
Notice that bind returns any meaning any type checks on the returned function is turned off, which leads to subtle bugs. Take the following for example:
// Assume the definition for `router.get` is something similar to this:
get(routeBase: string, callback: (req: Request, resp: Response) => void)
// ... and in the place you are calling it
private all(param: number): void {
}
this.route.get(this.routeBase, this.all.bind(this));
// No compiler error, but `all` and the callback parameter expected by `route.get` don't match!
If you would like to keep type checking you can use something like below instead of bind:
this.route.get((req, resp) => this.all(req, resp));
See: https://github.com/Microsoft/TypeScript/issues/212
I am using the node request module which is setup as follows:
request(object,function(data));
The function is a callback with the response data in it. I want to feed in a predefined set of objects, and wrap the request function in another function like so:
var quickReq(object,func){
request(object,func);
}
quickReq({
"method":"GET",
"url":"http://someapi.com",
}
,function(error, response, data) {
res.send(data);
});
Is this valid async code?
Is this valid async code?
Yes, yes it is.
It's not at all clear what you're trying to do, but the first parameter to request's callback is an error code, and the second parameter is the returned content (assuming it succeeded).