Returning the Result of a $.getJSON-Function - javascript

I need to load a php-script with ajax, which creates a JSON-result.
An example of the getEvent.php is:
[{"id":"1","start":"Wed Jul 18 12:00:00 GMT+0200 2012","end":"Wed Jul 18 13:30:00 GMT+0200 2012","title":"leer"}]
In order to transmit this result to another function, I have to be able to assign it to an variable. I tried it many ways, but it has never worked out.
function loadEvents(){
var cdata;
$.getJSON({
type: 'GET',
url: 'getEvent.php',
asynch:false,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(jsonData) {
cdata = jsonData;
},
error: function() {
alert('');
}
});
return cdata;
}
cdata = jsonData; doesnt seem to work
I have only found ways to asign parts of the result (jsonData) to a variable, but it seems that the entire jsonData can't be returned.
Can anybody help me with my problem? I have to return the complete jsonData to another function...
Thanks

getJSON is an asynchronous function (expectiong just a url, no settings object (Docu)), meaning that it will return a result as soon as the answer from the server is done. In the meantime your function continues execution. Thus, at the moment you return cdata, your success function hasn't executed yet. You need to either use a callback or set the function to be synchronous (which you are trying to do but have a typo in there - it's async without h - also if you want to pass additional settings, you can't use getJSON() but have to use $.ajax().
instead of making the call synchronous, using the callback is probably the better solution:
instead of
success: function(jsonData) {
cdata = jsonData;
},
write:
success: function(jsonData) {
workWithResult(jsonData);
},
// this is called the "callback" function, it is executed when the ajax-request
// returned successfully
function workWithResult(data){
// now you can work with the data, which is guaranteed to exist
}

First thing, why are you using getJSON?
$.ajax seems to suit more to your requirement.
Second,
The moment you return the cdata comes before the server responds. Your success handler will be executed once the server responds. In the current case, you won't be getting the data you are looking for. :)
What you can do to get around with this is to make the variable cdata global.
And just assign the value to cdata in success handler (which you have done already)
PS : Making variables global is not a good programming practice. (Or at least I don't recommend making use of global variables)
Post your specific requirement, like in what way you are going to use the returned value. So that we can see how we can avoid that global beast.
for eg:
success: function(result){
yourTargetFunction(result); // call the target function with returned data as a paramenter to it
}

Related

do I need parenthesis when using a named function as an jquery ajax success callback

if I have a function defined earlier, do I need to include parenthesis when specifying that it should be used for a success callback?
what would be the difference if I did?
as in
function fish_food(){//do something}
$.ajax({
url: '/',
success: fish_food
});
or
$.ajax({
url: '/',
success: fish_food()
});
fish_food on its own (without parens) acts as a reference to the function object. It allows you to pass the reference to the function around to be invoked at some later date.
fish_food() (with parens) is a function invocation expression, which causes the function to be executed. The function code is evaluated and run with a value optionally being returned.
With the AJAX code you supplied (and all async JavaScript involving callbacks) you want to use the fish_food version (without parens). This passes the AJAX code a reference to your success function, to be executed asynchronously once the AJAX code has completed its round trip to the server and back.
No.
Parentheses will tell the browser that function fish_food needs to be executed immediately, and the value has to be returned to a success property.
You want the no-parens version. The reason is that the parentheses tell JavaScript to execute the function right away, rather than just reference it by name, so your success callback would actually be the results of invoking fish_food() whenever you are executing the AJAX call (which is probably going to be an error involving undefined).
this will work
$.ajax({
url: '/',
success: fish_food
});
You don't need the parenthesis. Using parens would invoke the function, what it needs is just a name which is equivalent to function pointers in C/C++.
Having the parenthesis causes the function to execute then and there, that is why you need first version else success stores return value of the function.
$.ajax({
url: '/',
success: fish_food
});
is correct.
When you use success: fish_food(), it will be executed right away and the return is set to success.

jQuery Async Issue, Variable Assignment After GET Request

I'm sure the solution is staring me right in the eyes, but I just cannot see it. I am trying to load an object from an outside file source. I've tried it several which ways using jQuery's built in methods, but keep returning undefined. Is my issue the scope? I need partnerData right where it is because of other dependent methods in my script. I don't want to operate the rest of my site's functions from within the $.get callback. Any help is greatly appreciated, here's the code:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
});
console.log(partnerData); /* returns undefined instead of object */
});
EDIT:
Thanks for all the feedback everyone. This is the solution I went with:
var partnerData;
$.ajax({
url: 'data/partners.json',
dataType: 'json',
async: false,
success: function(data) {
partnerData = data;
}
});
The reason why you're seeing undefined is because ajax requests are asynchronous by default. This means your get method gets invoked and the code flow moves down to the next statement while the request executes in the background. Your callback function is later invoked when the request completes.
Using callback functions is a common pattern used in situations like this. But you seem to be saying you don't want to do or can't do that. In that case, you could use async: false which would force the request to be synchronous. Keep in mind however, that your code will be blocked on the request and if it's a long-lived request, the user experience will degrade as the browser will lock up.
P.S. You shouldn't need to parseJSON - if response has the correct mime-type set, jQuery will intelligently guess the type and parse the JSON automatically. And in case the server isn't sending back the correct mime-type, you can also explicitly tell jQuery what the expected return data type is; see the dataType argument to $.get() .
One way you might modify your code, to force synchronous requests:
$.ajax({
type: 'GET',
url: 'data/partners.json',
success: function(file){
partnerData = $.parseJSON(file);
//ideally you would perform a callback here
//and keep your requests asynchronous
},
dataType: 'json',
async: false
});
function is proccessed to the end event when ajax is still being proccessed. insert it into callback function
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
console.log(partnerData);
});
});
I would say that your problem is the same of the one that I just solved, if $.get is AJAX! and it is setting a variable, to read that variable outside the callback you need to wait the response! So you have to set async=false!
console.log in synchronous and get is async.
try:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
test();
});
function test(){
console.log(partnerData);
}
});

Set javascript global variable to JSONresult?

how do i set a js global variable to a json result set in the onload event?
var global = [];
$.getJSON("<%: Url.Action("myUrl", "con") %>/",
function(data) {
$.each(data, function(key, val) {
global.push(val);
});
});
global does not have a value set on load, i need to access it outside the json call...
You again. Maybe try
var result;
$.ajax({
url: '<%: Url.Action("myUrl", "con") %>/',
dataType: 'json',
async: false,
success: function(data) {
result = data;
}
});
// process result here
You don't need to set global to an array. Just assign the value.
var global = null;
$.getJSON("<%: Url.Action("myUrl", "con") %>/",
function(data) {
$.each(data, function(key, val) {
global = val;
});
});
That code should work just fine. (Live copy) Sounds like there's a problem with the ajax call not returning the data in the form you expect.
As #marc (indirectly) points, you have to understand the nature of the ajax call, and event model.
The ajax call is executed as soon as the JS file is parsed, byt result is returned asynchronously. So, your code timeline would look like
00 set global = []
01 AJAX call /someurl/ -------------------\
02 check global /* it's empty */ \
03 do something else [process AJAX call on server, send result]
... /
42 AJAX call is completed <----------------/
43 call success ----------------------------------> global.push(result)
44 at this point of time you can access global
This is a timeline, not the execution order. The time between the AJAX call and the response could be arbitrary, including the case of timeout or server-side error
So, what should you do?
1) the normal solurtion for JS - a callback, the success function you already have could either
1.1) set global and call the other function, or
1.2) do the desired actions with data
2) event - better if you suppose to use the data in multiple parts of the code, read for jQuery events mechanism
3) synchronous call, as #marc suggests - this should be avoided in 99% of cases. The only case I know when itt might be needed is when you have to requst for mandatory data from the 3rd party source, and even in this case you could do it on server (though at least synchronous AJAX is acceptable)

jQuery: insert html with javascript, waiting for it to run

I'm using $.ajax method to pull some html code and insert it into a 'div.listbox' element, using $('div.listbox').html() method.
I'm aware that .html will insert all HTML code, and execute all javascript code found under the HTML code.
What is actually happening:
$.ajax({
async: false,
url: 'ReturnSomeDataAsJSON',
data: {some_needed_data},
dataType: 'json',
success: function(data){
$('div.listbox').html(data.body)}
})
This data.body has a javascript that will make a call to an asynchronous function that will update an element inside the HTML under data.body.
Putting a .live function on the 'div.listbox' element, in order to listen to DOMNodeInserted event, I could see that the javascript method executed by the $...html(data.body) call updated 'div.listbox' element 6 times.
As this number could change, I can't just treat this as my solution, waiting to the element to change 6 times and then do what I want.
So I'm asking if it's possible to wait untill all javascript inside that .html call is executed before continuing to other javascript methods after the $.ajax call.
The only way would be to use a callback function inside your ajax-generated javascript, so you'd have:
//(ajax generated code)
<script>
...
$('div.listbox').css("color", "blue"); //For example, let's assume this code executes asynchronously
div_changed(); //This is the callback function
</script>
Then, in your main script you should have:
$.ajax({
async: false,
url: 'ReturnSomeDataAsJSON',
data: {some_needed_data},
dataType: 'json',
success: function(data){
$('div.listbox').html(data.body)
}
})
function div_changed(){
//Here put the code you want to be executed after changes are made
}
This is the only way, note that this is asynchronous.
Hope this helps. Cheers
JavaScript is a functional programming language meaning that you almost everywhere work with functions and can also pass functions as parameters. Let's describe your scenario: In scope A (parent element) you want to do something, but just when in scope B (child element) something happens and finishes. Only scope A knows what it wants to do, and only scope B knows when it finishes its job. So what do you do? Here are some solutions:
Hardcoding your logic of scope A in scope B (spaghetti code)
Get the function back from scope B and execute it in scope A (bad idea)
Pass the logic of scope A as a function to the scope B and let B be the agent to decide when to execute that.
The best method is the third item and this is the spirit of functional programming.
Solve by adding a listener to DOMSubtreeModified event, by doing:
$.ajax({
async: false,
url: 'ReturnSomeDataAsJSON',
data: {some_needed_data},
dataType: 'json',
success: function(data){
external_data = $(data.body)
var data_html = $(data.body)[0]
var data_script = $(data.body)[1].text
listbox_container = $('form#main_form div.listbox-container:nth(0)')
//fill body
listbox_container.html(data_html);
// attach listener
listbox_container.live('DOMSubtreeModified', check_listbox)
// eval script
eval(data_script)
// this script will (some time, asynchonously) update listbox_container
// by adding some data, that I need to deal with
}
})
function check_listbox() {
listbox_internal_ container = $('form#main_form div.listbox-container:nth(1)')
if (listbox_internal_container.length >= 1) {
// do what I want (deal with new data filled),
// because internal container (that will be created
// by the $.ajax call) now exists with some data filled by the
// eval(...) of the script
};
}

Javascript - local scope objects not accessible from nested function

I am trying to have a function grab an object from a php file on another page. I'm using the jQuery ajax function to to do the json grab, which is working correctly. The issue is when I try to return that object from the function.
The first time I log the object (from within the success function) it is correct in the console, but the returned object from the function getGantt() logs as "undefined".
How do I get this object out of the function?
My code:
function getGantt(requestNumber){
var ganttObject;
$.ajax({
type: "POST",
url: "get_gantt.php",
data: {request_number: requestNumber},
success: function(returnValue){
ganttObject = $.parseJSON(returnValue);
console.log(ganttObject); //this logs a correct object in the console
}
});
return ganttObject;
}
$(function(){ //document ready function
var requestNumber = $('#request_number').text();
var ganttObject = getGantt(requestNumber);
console.log(ganttObject); //this logs "undefined"
}); //end document ready function
The A in Ajax is an important part of the acronym. Asynchronous JavaScript and XML is asynchronous.
$.ajax({success:someFunction}) means Make an HTTP request and when the response arrives, run someFunction
return ganttObject runs before the response arrives.
You should do anything you want to do with the data inside someFunction and not try to return data to the calling function.
The A in AJAX stands for asynchronous. So the call immediately returns and as soon as it finishes, the success callback is called.
So, simply change your code to use a callback:
function getGantt(requestNumber, callback) {
var ganttObject;
$.ajax({
type: "POST",
dataType: 'json',
url: "get_gantt.php",
data: {request_number: requestNumber},
success: function(returnValue){
callback(returnValue);
}
});
}
$(function() {
var requestNumber = $('#request_number').text();
var ganttObject = getGantt(requestNumber, function(ganttObject) {
console.log(ganttObject);
});
});
Btw, I've also removed this parseJSON stuff - setting dataType to json does the job and is less dirty.
I know why it's not returning it at least. The ganttObject may be in the same scope, but the success function is ultimately running in the readyState callback from the XMLHTTP object, so it's on a different thread than the getGantt function. Can you make the $(function(){... code apart of your success function?

Categories