I'm totally new to javascript and have difficulty in understanding the meaning of the scripts. :( Hope someone can help me or give some advice, thaks! :)
I have a javascript in which it call Ajax function like:
callAjax('../team.cgi', 'POST', data, function(text)
In the ajax2.js it define the function callAjax like:
function callAjax(url, method, data, handler, waittime, timeout_func)
My question is what's the parameter function(text)?
function(text) is the beginning of the definition of an anonymous function. Presumably the call looks something like this:
callAjax('../team.cgi', 'POST', data, function(text)
{
// do something with text
});
The function defined between those brackets takes a variable, text, and does something with it. This is possible in JavaScript because functions are first-class citizens. They can be assigned to variables, defined anonymously, etc.
Typically, you'd say the handler parameter of the callAjax function is a callback. It's a function that will be passed certain arguments when the Ajax call completes. This is typical of asynchronous code.
The snippet above is functionally the same as this:
function doSomethingWhenAjaxCompletes(text) {
// do something
}
callAjax('../team.cgi', 'POST', data, doSomethingWhenAjaxCompletes);
The only difference in the first is that the function isn't defined with the name doSomethingWhenAjaxCompletes; it's defined anonymously instead.
Without seeing the context of the handler function my guess would be that this is the returned value from the ajax call. For example, if team.cgi in your example above returns an xml list of teams then I would expect the text parameter in the handler function to be that list.
When issuing AJAX requests, execution does not halt and wait for the response to come back. Instead, the request is send and execution continues. You simply provide what is called a "callback" function which is called when the AJAX response is returned. Typically, the callback function takes a single argument containing the response object or message that was returned as the answer to your AJAX request.
callAjax('../team.cgi', 'POST', data, function(text) {
console.log('Got a response!');
console.log(text);
}
This simply sends the request. At some time later (after a pause due to network latency) you will see the console log message appear, indicating that a response was received and the callback function meant for "handling" the response has been called.
Related
I've followed this explanation here, but am still unsure how callbacks work.
I do my call here:
scene.foo(scene.myCallBack("mymap"));
And my callback stuff here:
1) scene.foo calls foo and passes in CallBack function with "mymap" JSON data
2) foo's $.ajax defines its success as the passed in CallBack. Once the data is processed, success calls the callback, myCallBack()
3) myCallBack attempts to getJSON from the file name and console.log it as a string with JSON.stringfy
Am I not understanding this correctly?
foo : function (callback) {
$.ajax({
success: callback //once AJAX request is successfull, $.ajax will call callback (myCallBack) and pass response back to callback
});
},
myCallBack : function (name) {
$.getJSON("C:/Users/danniu/Desktop/JavaScript/tilemap/maps/" + name + ".json", function (data) {
var myJSONText = JSON.stringify(data);
console.log("json: " + this.myJSONText);
});
},
You're close to the solution.
scene.foo(scene.myCallBack("mymap")); first exectue scene.myCallBack("mymap") and then the result is passed to scene.foo(...)
It's similar to write:
var result = scene.myCallBack("mymap");
secene.foo(result);
This is pretty weird in this case, because scene.myCallBack("mymap"); doesn't return anything interesting to scene.foo
Note that $.getJSON(...) already does an Ajax request for you.
As soon as you stick parentheses on, it stops being a callback. scene.myCallBack can act as a callback; scene.myCallBack("mymap") is just undefined (the return value of your function, as it does not have an explicit return statement and thus implicitly returns undefined).
If you want to have he $.ajax do myCallBack on success AND have custom arguments with it, you need to wrap it:
scene.foo(function() { scene.myCallBack("mymap"); });
Or equivalently,
fooCallback = function() { scene.myCallBack("mymap"; };
scene.foo(fooCallback);
EDIT to clarify some concepts:
And can you explain why putting parentheses on it makes it not a callback?
Putting parentheses on a function executes a function, giving a value back. A callback must be a function.
For example, let's say your Mum wants you to eat an apple when you get home. She could leave you a note, "Growler, when you get home, eat an apple!":
var eatApple = function() {
growler.eat('apple');
}
growler.on('getHome', eatApple);
is one way to write such a thing. However, if you write
growler.on('getHome', eatApple());
it's like your Mum feeding you an apple, then writing a note "Growler, when you get home, __" and placing the apple core on the blank. I don't know about you, but I'd be rather surprised by such a note; and I daresay your JavaScript interpreter is likewise surprised as well.
A callback is a function to be done at a later time. If you execute it (with parentheses), you are only left with the function's results; and thus the function is not a callback, since your event will try to call back the result (the apple core), and not the function (process of eating an apple).
(An advanced topic is a function that returns a function; in this case, the result can be the callback, such as, growler.on('getHome', whatShouldIDoNow()). whatShouldIDoNow is still not a callback; the function that it would return would be.)
If $.getJSON is already an AJAX request, how can I get the callback from that?
I do not understand the question. You provide $.getJSON with callbacks at the time you invoke it; those functions will be called back at the appropriate time, if such happens.
I need to call the same callback function multiple times, and so I don't want to have to repeat it, but it takes a response, and this response is somehow not available to the calling function unless I explicitly define it. Basically this is what I have:
// The callback function
function foo(response){
//do something with the response here
}
// The calling function
mainActivity(data, function(response){
// Upon receiving the data in the form of 'response', do foo to it
foo(response);
});
What I would ideally like to do is:
mainActivity(data, foo(response)}
But I can't seem to figure out how.
Simple.
mainActivity(data, foo);
Though not if you're continuing to call foo() in mainActivity().
Reasoning:
mainActivity(data, foo(response)) calls foo(response) and passes that to mainActivity(data, callback). If foo(response) doesn't return a function, it's not going to be very successful when mainActivity tries to call it as a function (which would be callback(response) in the notional declaration).
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
I'm having trouble with callbacks mainly because I don't understand how they're working (or supposed to work).
I have my function:
function checkDuplicateIndex(values, callback) {
$.ajax({
type: "POST",
url: url,
data: "command=checkIndexAlbumTracks&" + values,
dataType: "html",
success: function(data){
var returnValue = data.d;
callback(returnValue);
}
});
}
And then within a submit event, how do I properly call checkDuplicateIndex so that I can alert() the value?
This ended up being a long answer, so I'm going to try to split it into pieces.
Functions in Javascript
So within javascript, a function is an object that can be passed around, assigned to a variable, etc, just like any other data type. The difference is that a function, rather than being a string of text, number, etc, is a block of code waiting to be executed.
This is often confusing to people starting out with programming because usually when you write code, it is executed when you run the program. But for functions, this is not the case. When you write code inside a function, it waits there not executing until you call the function. If you do not call the function, the code is never executed. Let's check out a quick example:
function say_hello(){
console.log('hello!');
}
What you see here is called a function declaration. This means you are creating a function, which is a block of code waiting to be executed. If you run this code, nothing will be logged to the console. Now let's look at a function call.
function say_hello(){
console.log('hello!');
}
say_hello();
So here we declare the function just like before, but below we call it. A function call is just the name of the function followed by open and close parens. If the function takes arguments, they will be inside the parens, but no need to worry about that for now. If you were to run this code, you would in fact see hello! logged to the console, because the function was called, which executes the code inside.
Asynchronous Code
Now, let's switch gears for a second. When you make a jquery ajax call, jquery abstracts a lot of code into the library. They take care of setting up the XMLHttpRequest, firing it off to the place you specify, and collecting the result, and they do this in a way that works cross-browser. But since javascript is asynchronous, as soon as the ajax call goes off, javascript keeps executing code after the ajax call, because who wants to wait around for someone else's server to respond while you could be still getting in that work. So if you fire off something like this:
$.ajax({
url: 'http://google.com',
success: function(){ console.log('done!') }
});
console.log('after ajax call');
...you may be surprised to find that it logs after ajax call before logging done!. This is because, as stated earlier, in javascript calls that deal with I/O are often asynchronous.
So if the ajax call is made and it immediately continues executing code even if the ajax call has not finished, how can we specify code that will run when it's finished? This is where everything comes together. By providing jquery with a function, which as we remember is a block of unexecuted code, we can provide a way for ourselves to write code that is executed only after the ajax call has finished by passing the block of unexecuted code to jquery and saying essetially "hey jquery, take this code, and when the ajax call is finished, call it and pass in any data you got out of it." How convenient!
The way we do this is through the success and error properites of jquery's ajax function. If the request was successful, it will call the function we pass to success, and I assume you can guess what happens if there was an error.
Putting It All Together
Asynchronous code and first class functions are two of the most confusing parts about javascript, and once you understand these two concepts, you'll be in a great spot, although it may take a while to get there. So it's important to think carefully about it and experiment. Let's talk through a couple ways to handle the example you are working with here, about jquery ajax.
First, we can try making our own function and passing the name of the function to the success handler. Then when it comes back, it will call the function. Let's take a look:
var my_callback = function(data){
console.log(data);
}
$.ajax({
url: 'http://google.com',
success: my_callback
});
This is an interesting way of doing it. Here we have assigned an anonymous function to a variable, then passed the variable name to the success handler. This will work fine. Now let's try another way:
function my_callback(data){
console.log(data);
}
$.ajax({
url: 'http://google.com',
success: my_callback
});
Here, we define a named function and do the same thing. This will work the same way. Named functions in javascript can actually be declared after the are used, so you could move the function declaration below the ajax call and it would still work. Try this out. This is a nice advantage to named functions.
Finally, let's take a look at a third way we could handle it:
$.ajax({
url: 'http://google.com',
success: function(data){
console.log(data);
}
});
Here, we define an anonymous function right inline on the success handler. This works exactly the same as either of the other two options. In all three of these ways, jquery receives a function declaration, and calls it when it needs to, which is after the ajax request has come back.
I know this is a super long answer, but what you are confused about here are some of the core concepts of javascript, and I thought it would be more helpful to go over them here than to just solve your problem and give you the answer without explanation of the concepts. In fact, I haven't actually tackled your problem here at all, but you will easily be able to solve it yourself after understanding these concepts. If you are still having trouble, drop a comment and I'll try to clarify more.
Given the above code, you would call it like this within your submit handler:
var values = '…';
checkDuplicateIndex(values, function(returnValue) {
alert(returnValue);
// additional processing here...
});
I'm sort of a noob with this so please forgive me :)
I can't get this one part of the function to update the variable. Could anyone possibly take a look a see what I'm doing wrong?
http://pastie.org/private/zfnv8v2astglabluo89ta
From line 142 thru 172 I'm not getting any results in the end. I've tested inside that function to make sure it is actually returning data, but the "body" variable is passing back up after line 172. So if I look at my generated HTML on the page, it simply looks the function skips from 140 to 174.
Thanks for any feedback!!
Your $.get is asynchronous. That means it will finish sometime AFTER the rest of the code, thus you won't see it's effect on the body variable inside that function. Instead, it's success callback function will be called long after this function has already finished.
To chain multiple asynchronous ajax calls like you have here, you can't just use normal sequential programming because asynchronous ajax calls aren't sequential. The network request is sent, then your javascript continues executing and SOMETIME LATER when the response arrives, the success handler is called and is executed.
To run sequential ajax calls like you have, you have to nest the work inside the success handler so that the ONLY code that uses the response is actually in the success handler. In pseudo-code, it looks like this:
$.get(..., function(data) {
// operate on the results only in here
// a second ajax function that uses the data from the first
// or adds onto the data from the first
$.get(..., function(data) {
// now finally, you have all the data
// so you can continue on with your logic here
});
// DO NOT PUT ANYTHING HERE that uses the responses from the ajax calls
// because that data will not yet be available here
});
You cannot do what you're doing which is like this:
var myVariable;
$.get(..., function(data) {
// add something to myVariable
});
$.get(..., function(data) {
// add something to myVariable
});
$.get(..., function(data) {
// add something to myVariable
});
// do something with myVariable
None of those ajax calls will have completed before the end of your function. You have to follow a design pattern like in my first example.
For more advanced tools, one can always use jQuery deferreds which are just a different way of defining code to run after an ajax call is done. It looks a little more like sequential programming even though it's really just scheduling code to run the same way my first code example does.
Function 8 will be invoke after line 174-180. You must put code from 174-180 line to the end of function
What I want is for data retrieved from one function to be displayed in another . I was told that using a global variable would allow me to accomplish this What is the best way to store a value for use in a later function? I'm hearing global variables are evil.
Here is what I tried. http://jsfiddle.net/8j947/17/
When I try to display the global variable as an alert it comes back as undefined (which might not be viewable on jsfiddle). I'm thinking this is because the data isn't actually getting stored, but I've only been coding for 3 weeks, so what do I know. If you guys could help me out by showing me what I did wrong or proposing an alternate solution that would be great.
Your alert function at the bottom is executing immediately after getCrossDomainJson is called, and before the callback function passed into getCrossDomainJson is called. Since the someProperty property is set inside the callback function, when you refer to it in the alert, it hasn't actually been set yet.
Give your alert function a name and call it somewhere else AFTER the callback function completes.
function getCrossDomainJson(url, callback) {
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?callback=?",
data: {
q: 'select * from xml where url="' + url + '"',
format: "json"
},
dataType: "jsonp",
success: callback
});
}
var MyStatus = {};
getCrossDomainJson("http://xdiscgolfplanetx.channel-api.livestream-api.com/2.0/getstream", function(data) {
// data is in JSON format:
console.dir(data);
if (data && data.query && data.query.results && data.query.results.channel) {
var isLive = (data.query.results.channel.isLive);
MyStatus.someProperty = data.query.results.channel.isLive;
// alert (isLive)
if (isLive == 'true') {
alert ('working')
}
alertSomeProperty(); // now that the someProperty property has been set and MyStatus
//is global, you'll see that you can refer to it even outside of this block
}
});
function alertSomeProperty(){
alert (MyStatus.someProperty)
}
This is a classic mistake when using asynchronous programming. You can no longer think of a single stepwise order of execution, call function a(), then b(), then c(). When using any form of ajax call, it is usually asynchronous. That means that calling the function only starts it's execution.
It will then run in the background and the rest of your javascript will keep running and finish. Then, sometime later, the ajax call will complete and it will call it's success function. ONLY from that success function or any other code that you call from the success function can you actually use the results of your ajax call. So, what you essentially have to do is start the ajax call and then your javascript code finishes for the moment. You then write a success function which will pick up execution of the rest of what you need to do when the ajax call completes. At that point, you have your JSON data and you can do with it what you want. You can take that data and call other functions, passing it along to them so they can operate on it.
So, kick of your second step of execution from the success handler. Whatever you need to do with the retrieved data should start in the success handler.
So, if the flow of execution you wanted to do was this:
a();
b();
getJSONdata();
c();
d();
You would have to structure it like this:
a();
b();
getJSONdata("xxx", function(data) {
c(data);
d();
})
function c(myData) {
// do something with the passed in data
}
where c() and d() are happening in the success function from retrieving the JSON data and they are called ONLY after the data is available.