I have this code which assigns a listener to the request object and when data comes, the function is executed. My question is, how the "chunk" variable is getting its value on the function call? Is this some kind of implicit assignment to the request object? I have seen similar patterns in JS but didn't really understand how they work. Any clarification will help.
request.on("data",function(chunk){
response.write(chunk.toString().toUpperCase()) ;
})
The code that emits the "data" event on the request object (inside of the request object) passes the chunk parameter to the event handler. Since the request object inherits from an eventEmitter, the code inside the request object that wants to announce the availability of some data does something like this:
request.emit("data", chunk);
That, then causes the event handler you registered for the "data" event to get called with chunk as the argument.
This is the same as any event handler in Javascript. The code that triggers the event sets the arguments for the event handler. You must declare an event handler function that has arguments that match what will be passed to it which you are doing here.
This is pretty much how callback functions work in Javascript. The system the calls the callback determines the arguments the callback will be sent. You then declare your callback to match that and register that callback with the system that will be calling it (sometime in the future). In this case, because it's an EventEmitter, you register it with .on(). In other cases, you might register it some other way (like with promises, you would use .then() or .catch()).
Related
So, I wrote the following function:
function getData() {
var data;
$(function () {
$.getJSON('https://ipinfo.io', function (ipinfo) {
data = ipinfo;
console.log(data);
})
})
console.log(data);
}
The problem with the above is the 2nd console.log doesn't retain the info from the assignment inside the jQuery and logs an undefined object. I'm not exactly sure what is wrong, but I believe it to be something quite minor. However, as much as I've searched online, I haven't found an answer for this particular problem.
One line: Javascript is Asynchronous.
While many struggle to figure out what it exactly means, a simple example could possibly explain you that.
You request some data from a URL.
When the data from second URL is received, you wish to set a variable with the received data.
You wish to use this outside the request function's callback (after making the request).
For a conventional programmer, it is very hard to grasp that the order of execution in case of JavaScript will not be 1,2 and then 3 but rather 1,3,2.
Why this happens is because of Javascript's event-loop mechanism where each asynchronous action is tied with an event and callbacks are called only when the event occurs. Meanwhile, the code outside the callback function executes without holding on for the event to actually occur.
In your case:
var data;
$(function () {
$.getJSON('https://ipinfo.io', function (ipinfo) {//async function's callback
data = ipinfo;
console.log(data);//first console output
})
})
console.log(data);//second console output
While the async function's callback is executed when the data is received from the $.getJSON function, javascript proceeds further without waiting for the callback to assign the value to the data variable, causing you to log undefined in the console (which is the value of the data variable when you call console.log.
I hope I was able to explain that.!
Here is the Class: http.Server documentation
[Q1]: Is function(request,response){...} the request Event's Listener?
[Q2]: if It is,from my understanding,whenever there is a request, the listener gets called?
[Q3]: According to the following,
Does it mean if I pass in a listener as a parameter, it will be registered on request event automatically?Can I pass in any function Object?
If I pass in function(request,response){...} ,is it the so called callback function when it's triggered by a request event?
Not quite sure about the definition of callback function
requestListener is a function you pass to the http.createServer() method. If you pass that function, then it will get called on every incoming request that the http server receives.
And, when it gets called, it will be called with two arguments, a request object and a response object in that order.
The requestListener function that you pass to http.createServer() is referred to as a callback function because you're passing a function that will get called back later by some other code.
Here's a simple example:
// Create an simple http server that knows about one request URL
var server = http.createServer(function(req, res) {
if (req.url === "/") {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
} else {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('not okay');
}
});
[Q1]: Is function(request,response){...} the request Event's Listener?
It is a callback function that is automatically registered for the request evnet and thus is called for every incoming http request.
[Q2]: if It is,from my understanding, whenever there is a request, the
listener gets called?
Yes.
[Q3]: Does it mean if I pass in a listener as a parameter, it will be
registered on request event automatically?
Yes.
Can I pass in any function Object?
Yes. You must declare the arguments appropriately as request and response in that order, but you can name those arguments anything you want. Their values are passed as the first and second arguments. The names of the arguments are whatever you choose to use in your function. A usual convention is to use (req, res) or (request, response) as this makes your code more recognizable to other node.js developers.
If I pass in function(request,response){...} ,is it the so called
callback function when it's triggered by a request event?
Yes.
Not quite sure about the definition of callback function
It is just a function that you pass as an argument to another function. It can be either a function named that is defined as a named function or it can be an inline anonymous function as shows in the example above. It does not matter which it is. It is called a callback function because it will be "called back" by some other code at some time in the future.
I am fairly used to RX having used it in .NET and Java, I am expecting to be able to do the following:
Rx.Observable.fromCallback(websocket.onmessage)
.map(...)
.subscribe(...);
however, the console has the following:
Uncaught TypeError: Rx.Observable.fromCallback(websocket.onmessage).map is not a function
which would appear to indicate that the fromCallback is not returning an Observable.
What am I doing wrong here? Have I misunderstood what fromCallback is doing and I need to use a Subject? Can I not wrap some arbitrary handler in an observable?
You are actually looking for fromEvent or fromEventPattern:
Rx.Observable.fromEvent(websocket, 'message').map(/*...*/).subscribe();
Rx.Observable.fromEventPattern(
function add(h) { websocket.addEventListener(h); },
function remove(h) { websocket.removeEventListener(h); })
.map(/*...*/)
.subscribe();
The first one will attempt to use some of the standard ways of subscribing to an event emitter, which WebSocket is. However, if that fails you can use fromEventPattern instead to specify how handlers are added or removed from your object.
One additional note, JavaScript does not pass along an implicit reference to the instance of the object you are using as C# and Java do, so your code fromCallback(websocket.onmessage) is not passing along websocket, it is passing along the reference to the method from the function prototype. this will be determined at execution time.
Rx.Observable.fromCallback is for functions whose last argument is a callback function which is a standard pattern for asynchronous JavaScript code. Further, the fromCallback method does not return an Observable it returns a function that when called returns an Observable i.e.
function methodWithCallback(arg0, arg1, cb) {
setTimeout(function() {
cb(arg0 + arg1);
}, 2000);
}
var newMethod = Rx.Observable.fromCallback(methodWithCallback);
//[After 2 seconds] 3
newMethod(1, 2).subscribe(console.log.bind(console));
I'm trying clone a json object inside a function wanting to access the object outside the function. But when function is done, the object still seems to be undefined. Seems like it's not the same variable?
var jsonUserObj;
$.getJSON("user.json", function(content){
jsonUserObj = $.parseJSON(JSON.stringify(content));
console.log(content);
console.log(jsonUserObj); //looks fine!
});
console.log(jsonUserObj); //undefined
inside the callback function it contains all the data, but it does not remain outside of it. How to make it assessible globally?
$.getJSON is asynchronous so console.log at the end of your code runs before $.getJSON returns its result.
You should modify the variable inside the callback (where it looks fine) and then use the variable inside that function, this callback is the only place where you can guarantee your variable is set.
You could also use the synchronous version of $.ajax but that's really not recommended (and probably unnecessary).
You got a typo:
console.log(jsonUserObject);
It should be
console.log(jsonUserObj);
You need to declare var jsonUserObj outside a function.
Also it looks like you have a typeo, is it jsonUserObj or jsonUserObject?
Could it be a question of timing? If that getJSON method is firing asynchronously then it may not have returned it's value by the time you have fired the last line. Does that make sense?
$.getJSON performs an ajax call, which is asynchronous. The code after it will continue evaluating while it waits for a response. When the response comes back, the program flow will jump back into the success/error/complete handlers of the ajax call.
tldr: Anything you do with data from an ajax call must be in the success handler of that ajax call.
I'm having issues getting a variable declared in an .click function to be updated in a Get function within the click function. I've gathered that even though the variable has the same name, within the Get function it is really declaring it anew.
I've tried to find examples helping me, but it appears to me that the Get method is such a specialized function that the examples didn't seem to apply.
I would like the value of 'SettingContentToEdit' to get updated with information retrieved with the Get function.
Below is the code.
Thank you for your help!
$(".cellSetting").click(function () {
var clickedClass = $(this).attr("class");
var clickedItemID = $(this).attr("id")
var SettingContentToEdit = "not changed";
var JSONSend = {
'ItemName': clickedItemID, //send the item name so the model knows which one to pull up!
'ItemSetting': clickedClass
};
$.get(
'/Home/getItem',
JSONSend,
function (data) {
// $('#dialog').html(data.ItemSettings[data.SettingToEdit]);
SettingContentToEdit = data.ItemSettings[data.SettingToEdit];
alert(SettingContentToEdit); //returns the correct info
}
);
alert(SettingContentToEdit); //returns "not changed"
});
Your issue is that your ajax call is asyncronous. The success handler for the get() function is called some time after your click handler and the alert() has already completed. You can refer to the local variables in your success handler, but the code that follows the success handler executes BEFORE the success handler does.
This is because your get() operate is asynchronous. Calling it just STARTS the networking operation and then your javascript execution continues (while the networking operation works in the background). After starting the networking operation, your alert() is called. Then, some time LATER, the Ajax call completes and the success handler is executed.
This is a very common mistake and has indeed been asked and answered hundreds (if not thousands) of times here on SO (I've personally probably answered 20-30) so you are not alone in missing this understanding at first.
If you want to use the results of the ajax operation, then you need to put the code that does that either in your success handler or put it in a function that you call from your success handler. You cannot put it after the get() function because it will execute too soon before the results are known.
AJAX is asynchronous. If you check SettingContentToEdit a second or so later than you are doing, you'd see the value has updated.
Either put your code inside the get function (where you have your alert showing the correct value) or make the request synchronous (you'll have to look up the jQuery docs because I don't use jQuery).