$.GET() didn't return value - javascript

i have script like this.
function getContactLastDateOfDeparture(contactId) {
$.get(
'/transaction/ajaxGetContactLastDateOfDeparture/'+contactId,
'',
function(data){
alert(data);
return data;
},
'json'
);
}
I test script above with console.log(getContactLastDateOfDeparture(2144)), when in alert phase it outputted string 2011-12-06, but when phase return it outputed undefined
How to make the return should be 2011-12-06 ?

You can't really do a return in an AJAX function, as it is asynchronous. It is better to call another function at the end if you want to pass along the value.
To do this, you can pass it along like this:
function getCall(param, callback) {
$.get('url', function (data) { alert(data); callback(data); }, 'json');
}

If you really want your function to return value from the ajax call, you can use $.ajax instead of $.get (essentially $.get is based on $.ajax with some simplified params); $.ajax has a parameter "async" that you can set to false to make the ajax call synchronous.
IMPORTANT - it is not recommended to use sync calls with ajax as it will freeze the js execution and might lead to unexpected problems.

http://fixingthesejquery.com/images/ajax101.png
You should read up about Ajax, asynchronous behavior and event driven programming. It just doesn't work like that.

Gus,
The first parameter is a url to a valid processing page (html, asp, php, etc).
EDIT (after being voted down):
A valid url, in your case, would be:
$.get('url', function (data) {
alert(data);
});
your url '/transaction/ajaxGetContactLastDateOfDeparture/'+contactId would
not "compute"
However,
'/transaction/ajaxGetContactLastDateOfDeparture/getContactID.php?contactID='+contactId
would!
Your processing file (.asp, .php, etc) would, then, return the value you are
expecting.

Related

JQuery ajaxSubmit response always in lowercase

I am making an ajaxSubmit call to a web service, that will return XML.
When I make a call to the same service using XMLHttpRequest.send, the response is correct.
However if I use:
$(form).ajaxSubmit({
error: function _(response) {
$(iframeEl).remove();
config.error.call(scope, Thunderhead.util.JSON.decode(response));
},
success: function _(response) {
console.log(response);
$(iframeEl).remove();
var result = response;
config.success.call(scope, result);
},
iframe: true
});
This returns the correct XML response, but all tags have been transformed to lowercase.
I've checked the call in the Network tab in the developer console, and the case is correct in there, but when it is returned by the ajaxSubmit, it is lowercase.
Does anyone know what is causing this or how to rectify it?
Are you using Malsups jQuery form plugin
This plugin does a lot of toLowerCase transforms, I've not looked too closely but it does seem to lowercase the tag names of something, so this is probably your culprit.
I'd recommend refactoring to using a simple jQuery.ajax() call instead
$(form).on('submit', function(e) {
var url = $(form).attr('action');
e.preventDefault();
$.ajax( url, {
error: function _(jqXHResponse) {
// your code
},
success: function _(response) {
console.log(response);
// your code
}
});
This might be happening, because js is assuming xml as an answer. There is no difference for most xml-parsers which case is used in xml tag names.
I suggest trying to change response data type.
For example there is such option in jQuery.ajax method: http://api.jquery.com/jquery.ajax/ (named dataType). I would try using "text" dataType if case is really important.
Some further issues arose from this in the end, so just posting my eventual solution in case anyone else has this problem. I'm fairly new to javascript, so this might have been obvious to most, but it might help someone else out.
The success callback can actually take in 3 parameters, the third of which (arg2) is the actual response from the request, without any changes from the Malsups form plugin.
So in the end, the solution was simply to use this third parameter instead of the response parameter.
$(form).ajaxSubmit({
error: function _(response) {
$(iframeEl).remove();
config.error.call(scope, Thunderhead.util.JSON.decode(response));
},
success: function _(response, arg1, arg2) {
console.log(response);
$(iframeEl).remove();
var result = response;
config.success.call(scope, arg2.responseXML);
},
iframe: true
});

How Do I return a javascript variable from a function that contains a $.get() request

I've tried Googling this but could not reslove it. It may seem like a really simple issue to others but I'm baffled by it. I have the below code in which I get undefined for the first alert but I still get the correct values in the 2nd alert. BUT if I comment out the first alert (just the line with alert) then the 2nd alert output becomes undefined. Can any one explain why this is and how I may output the 2nd alert correctly without the first one, any Help is greatly appreciated.
function getDetails(ID){
var qArray = [];
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
});
//First Alert
alert("-> "+qArray[0]);
return qArray;
}
This is the 2nd alert which calls the above method:
var myArray = getDetails(4);
alert("myArray [0]: "+myArray[0]);
You can't return a value, the $.get() call is asynchronous.
You need to defer any operations on qArray until the AJAX call has completed, i.e. inside the callback.
Better yet, use deferred callbacks:
function getDetails(ID) {
return $.get('get_Question', {"Id":ID})
.pipe(function(json) {
return [json.value1, json.value2];
});
}
The .pipe deferred function creates a new promise which will ultimately return the desired array, but only once the AJAX call has completed.
You would then use this like this:
getDetails(ID).done(function(qArray) {
alert("-> " + qArray[0]);
});
Note that $.get() doesn't directly support error callbacks, but with deferred objects you can get access to them:
getDetails(ID).done(function(qArray) {
alert("-> " + qArray[0]);
}).fail(function(jqXHR, textStatus, errorThrown)) {
alert("The AJAX request failed:" + errorThrown);
});
Without this you'd need to build the error handling directly into the getDetails() function and then require some mechanism to tell the rest of the application logic about the error.
NB I've assumed that you don't really need to call JSON.parse() manually - if your web server returns the right Content-Type header then jQuery will do that for you automatically.
Ajax calls happens asynchroniusly, meaning you can't wait for the call to return and get the value. The way to do it is to employ a callback. Your example will become something similar to this:
function getDetails(ID, callback){
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var qArray = [];
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
callback(qArray)
});
}
Calling it will change a bit:
getDetails(4, function (myArray) {
alert("myArray [0]: "+myArray[0]);
});
The First Alert is called before the ajax call is finished, so the variable is still undefined.
This is because the $.get() is done asynchronously. There is no option for $.get() to pass parameter for async calls, so you should use $.ajax() instead and pass a param async: false
The $.get call creates a new asynchronous request for the resource in question.
When you call the first alert it is undefined because the request hasn't been completed yet. Also since you are forced to pause on the alert the request has time to be completed in the background. Enough time for it to be available by the second alert.
The same thing happens when you comment out the first alert. This time the second alert is called before the request is completed and the value is undefined.
You need to either make your requests synchronous or consider continuing execution after receiving the response by using a callback function within the success callback function you have already defined in $.get.
As several others have said, ajax-request are asynchronous. You could however set the async property to false to get a synchronous request.
Example:
function getDetails(ID) {
var result = $.ajax('get_Question', {
async : false,
data : { 'Id' : ID }
});
// do something with the result
return result;
}
I myself would have use a callback function instead beacuse async:false is bad practice and is also deprecated.
You'll need to rewrite $.get to use $.ajax and specify async: false
AJAX is asynchronous: you can't tell when the request will complete. This usually means you need to pass callback methods that will be called with the result of the request when it completes. In your case this would look something like:
function getDetails(ID, callbackFunc){
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var qArray = [];
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
callbackFunc(qarray);
});
}
getDetails(4, function(qArray) {
alert("myArray [0]: "+qArray[0]);
};

getJSON to string then loop through string

I have the following code which is included in a keypress function:
$.getJSON('dimensions.json', function(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
});
I'm trying to first get the JSON string, save it in a variable and then run the each(). I want to basically separate the each() to be unlinked to the getJSON() function because I don't want it to fetch the json file for every keypress.
I've tried this, but it didn't work:
var JSONstr = $.getJSON('dimensions.json');
$.each(JSONstr, function(index) {
$('#div1').append(index);
});
In your first example, you do $.each in the callback. The callback is executed by some other callback after there result is received, while $.getJSON returns immediately without waiting for the result (since there is no blocking in JavaScript by design).
Therefore the code in your second example can never work: the $.each begins before any result is received from the web server, probably even before the request is sent. Whatever the return value of $.getJSON is, it can't, by the design of JavaScript, be the result of AJAX request.
UPD: Saw your comment, now I understand what you wanted to do. Here's a simple example of how to do this:
function ActualHandler(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
function KeypressHandler() {
if (window.my_data) { // If we have the data saved, work with it
ActualHandler(window.my_data);
}
else { // Otherwise, send the request, wait for the answer, then do something
$.getJSON('dimensions.json', function(data) {
window.my_data = data; // Save the data
ActualHandler(data); // And *then* work on it
});
}
}
Here, the ActualHandler is not launched before the data is received, and once that happens, all subsequent clicks will be handled immediately.
The downside in this particular case is that if user clicks again while the first request is running, one more will be sent. But to fix that you would need to maintain some queue, which is kind of out of scope here.
You fell into the asynchronous trap. Your $.each() function doesn't wait for your $.getJSON() call to get the data. You can get around this by using the good 'ol $.ajax() function. Like this:
function processJSON(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
$.ajax({
url: 'dimensions.json',
dataType: 'json',
async: false,
success: processJSON(data)
});

jquery get call complete function not working

I have a web application that gets data with a get call. When it is called, it sets a static variable. After the call is complete I want to get the value, but the complete function that I call is not working, its calling it to fast because its null.
$.get('../Controls/myfullcontrol.aspx', {}, function (data) {
$('#SiteFullControl').html(data);
}).complete(function () {
$('#FullControlCount').html('Full Control (<%=GlobalClass.GlobalVariables.User.Count %>)');
$('#LoadingAjax').dialog('close');
});
Using Firebug or Chrome's Inspector, look at the XHR and ensure that the script is actually returning something.
Are you looking for data returned to the complete function?
Then you need a parameter in the function:
}).complete(function (data) {
You don't need the $.complete() method because the $.get() contains allready an success callback.
http://api.jquery.com/jQuery.get/
You could work with jQuery the Promise interface (introduced in 1.5).So you can chain multiple callbacks on a single request...
Take look: http://api.jquery.com/jQuery.get/#jqxhr-object
jQuery.get( url, [data,] [success(data, textStatus, jqXHR),] [dataType] )
$.get('ajax/test.html', function(data) {
//STUFF AT SUCCESS
});

Scoping Out the Javascript Function Scope Problem

It's very clear I don't understand how functions are scoped in Javascript. Here's the latest example:
function riseData() {
var jsonResult;
$.ajax({
success: function(data, textStatus, jqXHR){
jsonResult = jqXHR.responseText;
alert("Inside: " + jsonResult);
},
error: function (jqXHR, textStatus, errorThrown) {
$('#errLog').append('<br>Status: ' + qXHR.statusText);
}
});
return jsonResult;
}
$(document).ready(function(){
var intervalID = setInterval('UTCclock()',100);
alert("Outside: " + riseData());
});
When I execute this, the "Inside" alert functions properly, but the "Outside" alert displays "undefined", even though riseData() is obviously defined only a few lines earlier. There is a $.ajaxSetup earlier in the code which defines the parameters for the ajax call. The ajax call successfully returns the requested data in the "Inside" alert.
I just haven't the slightest clue how to make the necessary data (jqXHR.responseText) available to other parts of the script.
Can anyone point me at a "Javascript Scoping for Dummies" how-to that addresses this issue?
Your example is scoped just fine. Your problem is you don't understand the implications of how JavaScript is mainly asynchronous.
Let me go through your example to show you.
Your document ready handler runs.
It calls riseData.
riseData declares a variable, jsonResult.
riseData calls $.ajax, which schedules an AJAX request to be done, but the response will happen later.
Since $.ajax is usually non-blocking/asynchronous, riseData continues and returns jsonResult. Since jsonResult has not been assigned yet because the AJAX request has not completed, the default value of undefined is returned.
In the document ready handler, you end up with alert("Outside: "+undefined);.
An event loop to a few milliseconds later, this happens:
The AJAX request is completed. jQuery forwards this on to your callback.
jsonResult is set, but riseData has already returned.
The alert inside riseData alerts with the new data, after the document ready handler has already alerted undefined.
There are two solutions to this problem. The first solution is simple, but often results in a worse user experience. This solution is to add the async: false option to $.ajax. This makes $.ajax block and freeze the browser.
The second solution is to adopt an asynchronous style for almost everything. That means making riseData accept a callback and calling it inside the AJAX response handler. Here's your code transformed with this method:
function riseData(callback) {
$.ajax({
success: function(data, textStatus, jqXHR){
var jsonResult = jqXHR.responseText;
alert("Inside: " + jsonResult);
callback(jsonResult);
},
error: function (jqXHR, textStatus, errorThrown) {
$('#errLog').append('<br>Status: ' + qXHR.statusText);
}
});
}
$(document).ready(function(){
//var intervalID = setInterval('UTCclock()',100);
// Unrelated, but it's better to pass a
// function into setInterval than a string.
var intervalID = setInterval(UTCclock, 100);
riseData(function(jsonResult) {
alert("Outside: " + jsonResult);
});
});
This is only partially a scope issue. Your ajax call is asynchronous, so the riseData() function returns a value before the ajax call is executed. Try setting your variable outside the method.
var jsonResult;
function riseData() {
$.ajax({
...
jsonResult should not only be available in riseData(), but also out. However, you'll still have the issue of exactly when it gets populated.
A link for a little more explanation:
What is the scope of variables in JavaScript?

Categories

Resources