I have this function which parses the JSON. I am getting undefined when I am calling it in a .live function.
Here is the function that I have created,
function getAbc() {
var details;
var id = $(this).attr('data-id');
$.ajax({
url : '/index.php/data',
type : 'GET',
data : 'persons[]=' + id,
success : function(data, textStatus, xhr) {
details = JSON.parse(data);
},
});
return details;
}
I am simply calling like this, getAbc(). And is there any way that I can access details variable in the function?
Use continuation passing style. The $.ajax is async in nature.
function getAbc(callback) {
var details;
var id = $(this).attr('data-id');
$.ajax({
url : '/index.php/data',
type : 'GET',
data : 'persons[]=' + id,
success : function(data, textStatus, xhr) {
details = JSON.parse(data);
callback(details);
}
});
}
function getAbc(function (details) {
console.log(details);
});
That's because ajax happens asynchronously. That means getAbc returns before success is invoked, because the request goes over the wire. You need to use details in the success callback, not after the getAbc method returns. Alternatively, in success call another method that uses details, and pass details to that method.
This is due to the way AJAX works.
AJAX requests are asynchronous, which means they do not return immediately.
When you make an AJAX call, a request is made that completes at an unknown time.
You can use a callback function to handle the results.
A callback function is a function that gets executed AFTER the response is received from the AJAX request.
You can specify a callback function and pass it to your AJAX call.
Related
I'm new to javascript and trying to understand if following thing is possible:
Let's say I use following ajax request construction in several places in my code (with different success callback functions - in this example only handleSuccessCallback()) and different url and data request param:
jQuery.ajax({
type: 'GET',
url: loadUrl,
data: data,
error: errorCallback,
success: function(response) {
this.handleSuccessCallback(response);
}
});
function handleSuccessCallback(response) {
Do something with response here...
}
I wanted to refactor this code in such way, that I don't need to create construction above each time I need to send request. I wanted to create a function in my utils class that will take url, request data and error/success callback. Something like this:
function sendAjaxRequest(url, data, errorCallback, successCallback)
jQuery.ajax({
type: 'GET',
url: url,
data: data,
error: errorCallback,
success: successCallback
});
}
Then, I wanted to call this function several times passing different arguments from my main script.
In my main code:
var url = "https://some url";
var data = {};
var errorCallback = handleErrorCallback();
var successCallback = handleSuccessCallback(); // ??? This function requires `response` argument being passed, how it can be done?
utils.sendAjaxRequest(url, data, errorCallback, successCallback);
function handleSuccessCallback(response) {
Do something with response here...
}
function handleErrorCallback() {
Do something with error here...
}
However, what I don't understanding is the following:
how can I pass success callback function (handleSuccessCallback(response)) to the sendAjaxRequest() function, if my handleSuccessCallback(response) needs params which is result of the success ajax callback itself(response)?
How can I pass this response param to handleSuccessCallback() when passing it to sendAjaxRequest() if I don't know yet what will be the response from ajax call?
When you want to call:
function sendAjaxRequest(url, data, errorCallback, successCallback)
You just need to give names of functions for errorCallback and successCallback. You are passing function references, so they can be called by other code. The params are provided at the point where those functions are called, like in your original example:
success: function(response) {
this.handleSuccessCallback(response);
}
Here the success function as defined in ajax with first parameter as response, so you have an anonymous function here with the first parameter as response.
So you just need to define your functions to match what they will be when they get called by ajax, e.g.:
var firstSuccessCallback = function(response) {
//do something;
}
var firstErrorCallback = function(error) {
//do something;
}
you can do:
sendAjaxRequest(url, data, firstErrorCallback, firstSuccessCallback)
Suppose I want to make an ajax call to the server and use the response to replace a section of existing document content. Would there be any reason to choose one of these methods over the other?
Option 1 - make the ajax call, and perform the replaceWith from the error/success functions. Example:
$.ajax({
type : 'GET',
url : '/some/path/here',
success : function(data) {
// process data here
$('#container').replaceWith(processedData);
}
});
Option 2 - call replaceWith, passing in a function that makes the ajax call. Example:
$("#container").replaceWith(function(){
var responseData;
$.ajax({
type : 'GET',
url : '/some/path/here',
success : function(data) {
// process data here
responseData = processedData; //
}
});
return responseData;
});
Second one is not an option. When you take the function out;
function(){
var responseData;
$.ajax({
type : 'GET',
url : '/some/path/here',
success : function(data) {
// process data here
responseData = processedData; //
}
});
return responseData;
}
This will return undefined. Cause, when the time function runs and returns, reponseData is undefined. Only, sometime in future, success function executes and sets responseData. However, your replaceWith code has already finished executing.
Go with option 1.
Option 1 is your only choice, as option 2 would not work as the call would execute asynchronously. This means your function would never return anything.
If you are looking to externalise the processing of the data returned from your AJAX call, just set the success parameter as a reference to the function you want to execute:
$.ajax({
type: 'GET',
url: '/some/path/here',
success: processData
});
function processData(data) {
// process data here
$('#container').replaceWith(data);
}
I have two javascript functions. from validateSearchStirng() i am calling checkSolrServerAvailibility(), from which i am expecting to return flag=1 if ajax request is successful otherwise flag=0. but each time checkSolrServerAvailibility() returning flag=0. Why so and what i need to do for getting correct result
function validateSearchStirng(sort,order,itemPerPage,showPage)
{
var serverflag;
serverflag=checkSolrServerAvailibility(sort,order,itemPerPage,showPage,query,solrURL);
if(serverflag==0)
{
var msg= "<hr /><font size="+size+" ><b>Solr Server Not Runing </b></font><hr /> ";
removeList();
$("#result").html(msg);
}
if(serverflag==1)
{
getSolrResponse(sort,order,itemPerPage,showPage,query,solrURL);
}
}
function checkSolrServerAvailibility(sort,order,itemPerPage,showPage,query,solrURL)
{
var start=itemPerPage*(showPage-1);
var end=itemPerPage;
var flag=0
$.ajax({
url: solrURL+"/solr/db/select/?qt=dismax&wt=json&&start="+start+"& rows="+end+"&q="+query+"&json.wrf=?",
async:true,
dataType: 'json',
success: function(json){
flag=1;
return(flag);
}
})
return(flag);
}
}
async : false
You should turn this flag to false.
Then you will get the desired results
You should probably forget about using JS functions this way and do it using callbacks. So basically instead of doing something like that:
serverflag=checkSolrServerAvailibility(...);
do something like that:
var processServerFlagCallback = function(flag){
// do something with your flag
}
checkSolrServerAvailibility(..., processServerFlagCallback);
and inside checkSolrServerAvailability, when you have information about success, invoke given callback with 1 as parameter, and in case of error - with 0 as parameter.
To see how to determine that an error occured during request, please see jQuery's .ajax() documentation on error parameter.
You need to redesign your solution to something like
function checkSolrServerAvailibility(sort,order,itemPerPage,showPage,query,solrURL, success, error){
$.ajax({
url: "",
dataType: 'json',
success: function(json){
success.apply(this, arguments);
},
error:function(){
error.apply(this, arguments);
}
})
}
function onAvailabilityCheck(json, textStatus, jqXHR){
getSolrResponse(sort,order,itemPerPage,showPage,query,solrURL);
}
function onAvailabilityCheckError(jqXHR, textStatus, errorThrown){
var msg= "<hr /><font size="+size+" ><b>Solr Server Not Runing </b></font><hr /> ";
removeList();
$("#result").html(msg);
}
function validateSearchStirng(sort,order,itemPerPage,showPage){
checkSolrServerAvailibility(sort,order,itemPerPage,showPage,query,solrURL, onAvailabilityCheck, onAvailabilityCheckError);
}
Since you are working with ajax request which by definition asynchronous in nature, your code will not work because once the client sent the ajax request to server it will not wait for the server response to comeback. It will keep executing the next lines... that means your flag will always be set to false.
To solve this problem my suggestion will be is to use callback methods to handle both success and failure cases as shown.
In the case of a successful ajax request the onAvailabilityCheck method will be called with the given parameters and if the ajax request is a failure the onAvailabilityCheckError method will be called.
I have the following method:
function priceRange(FESTIVALID){
jQuery.ajax({
url : '/actions/festheads.cfc?method=getPriceRangeByGUID',
type : 'POST',
data : 'FESTIVALID='+FESTIVALID,
dataType: 'json',
success : function(data) {
console.info("AJAX:qPrices",data.MINPRICE);
formatedPriceRange = '$ '+data.MINPRICE;
console.info("AJAX:formatedPriceRange", formatedPriceRange);
}//success
});//ajax;
//
return formatedPriceRange;
};
The second console.info correctly displays the formatedPriceRange,
but outside the function is undefined.
how can I access this variable out side the priceRange function?
Thanks
It's normal, that's how AJAX works. It's asynchronous, meaning that the jQuery.ajax function returns immediately and in this case formatedPriceRange hasn't yet been assigned a value and once the server responds (which can be for example 10 seconds later), the success callback is invoked and the variable is assigned a value.
So always consume the results of your AJAX requests inside the success callback function.
You also have the possibility to pass the async: false option to your jQuery.ajax call which will perform a synchronous request to the server and block until the result is retrieved. Obviously this will lead to your browser freezing during the execution of the request. So it would no longer be AJAX (Asynchronous Javascript And Xml) but SJAX (Synchronous Javascript and Xml).
You have to make sure that the AJAX request finishes before you access the price range data.
You need to expose the price range data outside the scope of the success function.
Here's how you can do it:
function priceRange(FESTIVALID, callback) {
jQuery.ajax({
url: '/actions/festheads.cfc?method=getPriceRangeByGUID',
type: 'POST',
data: 'FESTIVALID=' + FESTIVALID,
dataType: 'json',
success: function(data) {
console.info("AJAX:qPrices", data.MINPRICE);
formatedPriceRange = '$ ' + data.MINPRICE;
console.info("AJAX:formatedPriceRange", formatedPriceRange);
callback.call(this, formatedPriceRange);
} //success
}); //ajax;
}
var myFestivalID = 1;
priceRange(myFestivalID, function(priceRange) {
// this code runs when the ajax call is complete
alert('The formatted price range is:' + priceRange);
});
how can I access this variable out
side the priceRange function?
Like Darin said, you have to use your results in the success callback function.
Assuming you're using your current function like this:
var range = priceRange(festivalId);
// ... doing stuff with range variable
You'll want reorganize your code so that anything you do with the range variable stems from the success callback. For example, you can create a function to handle updating the UI with the new range:
function handleRangeVariabe(range) {
/// ... do stuff with range variable
}
Call it from success:
success: function(data) {
console.info("AJAX:qPrices",data.MINPRICE);
formatedPriceRange = '$ '+data.MINPRICE;
console.info("AJAX:formatedPriceRange", formatedPriceRange);
handleRangeVariable(formatedPriceRange);
}
Flower the steps of sample Code:
//declare function
function priceRange(FESTIVALID, functionCallBack){
//1º step
jQuery.ajax({
url : '/actions/festheads.cfc?method=getPriceRangeByGUID',
type : 'POST',
data : 'FESTIVALID='+FESTIVALID,
dataType: 'json',
success : function(data) {
//3º step, because this function will only trigger when server responds to request
//handle data in other function
functionCallBack(data);
}//success
});//ajax;
//more code
//2º step
//no return value, because this method no know when the data will return of server
//return formatedPriceRange;
};
var formatedPriceRange;
//using function
princeRange(1 , function(data){
console.info("AJAX:qPrices",data.MINPRICE);
formatedPriceRange = '$ '+data.MINPRICE;
console.info("AJAX:formatedPriceRange", formatedPriceRange);
});
Once again having problems being a new to javascript. I want to get the reply from my PHP script using JQuery's get. Here's my function
function getNext(){
var returnData = null;
$.get("get.php", {task:'next'}, function(responseText){
returnData = responseText; }, "text");
return returnData;
}
Now obviously the function returns null even though the request was successful. Why?
Thanks for your help in advance.
Because ajax is asynchronous, it acts independently on its own and so by the time the return statement completes, it hasn't been assigned yet.
function getNext(){
var returnData;
$.ajax({
url: "get.php",
data: {task:'next'},
success: function(responseText) { returnData = responseText },
async: false;
});
return returnData;
}
Note that this may "freeze" the UI because Javascript is single threaded -- it will wait until it receives the response from the server.
You may want to refactor it so that the action is called in the success callback. Could you show us what triggers the invokation of the getNext method?
try this
function getNext(){
var returnData = null;
$.get("get.php", {task:'next'},
function(responseText){
returnData = responseText;
alert('Data ' + responseText);
});
}
You will have to poll whether returnData contains actual data that you want periodically (or put your code into the callback method)