This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
I have an AJAX function that is called from a javascript function.
Something like this:
(CODE1)
//javascript function calling AJAX.
var function check(){
var status = chkHoliday(date,'Date Chosen');
alert('called');
return status;
}
//AJAX function
function chkHoliday(date,str){
var flag = true;
$.ajax({
type: "GET",
url: someurl,
async: false, //if commented, the alert() from the caller function is called before completion of this function.
dataType: "json",
success: {
flag = false;
}
});
return flag;
}
It works well. The only problem is that since async it is set to false, the web page sort of hangs for a while but then continues to proceed further.
To avoid this I read something about callback functions so i tried this out:
(CODE 2)
//javascript function calling AJAX.
var function check(){
var status;
chkHoliday(date,'Date Chosen',function(retVal){
status = retVal;
});
if(status != null){
alert(status);
return status;
}
else{
alert(true);
return true;
}
}
//AJAX function
function chkHoliday(date,str,callback){
var flag = true;
$.ajax({
type: "GET",
url: someurl,
//async: false, //if commented, the alert() from the caller function is called before completion of this function.
dataType: "json",
success: {
flag = false;
callback(flag);
}
});
//return flag;
}
this worked but the alert was called again before the AJAX function could complete stating "undefined". I don't know what I'm doing wrong.
I want, that the AJAX function should wait till it executes completely and then return to the calling function and run the next statements in the caller function with halting the process (i.e with the use of async). Also i want that the value returned by AJAX should be easily accessible to my caller function.
Put the alert inside the callback function:
chkHoliday(date,'Date Chosen',function(retVal){
status = retVal;
if(status != null){
alert(status);
}
else{
alert(true);
}
});
But note you cannot use the return statement anymore as what you have expected because it is asynchronous.
Since AJAX works asynchronous, it is a problem to place it in a function and return a value. To solve this use deferred with a promise. This will promise the ajax result to the caller. It is slightly different. Here is an example. Works like a charm for me.
Of course you will need to adapt it to your needs, but all you really have to do is create your data object.
var data = {}
function chkHoliday(data) {
var deferred = $.ajax({
method: "post",
url: ajaxURL,
dataType: "json",
data: data
});
return deferred.promise();
}
chkHoliday(data).done(function (response) {
console.log(response);
}
return from your php file with a
echo json_encode(array("success"=>"hello"));
Put the alert inside the callback
functions. or else alerts will work simultaneously inspite of success or error.
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
function ajax_test(str1){
var url = "None"
jq.ajax({
type:'post',
cache: false,
url: 'http://....' + str1,
success: function(data, status, xhr){
url=data;
},
error: function (xhr, status, e) {
},
async: true,
dataType: 'json'
});
return url
}
How can I set the global variable url to be the returned success ajax data?
In Javascript, it is impossible for a function to return an asynchronous result. The function will usually return before the AJAX request is even made.
You can always force your request to be syncronous with async: false, but that's usually not a good idea because it will cause the browser to lock up while it waits for the results.
The standard way to get around this is by using a callback function.
function ajax_test(str1, callback){
jq.ajax({
//... your options
success: function(data, status, xhr){
callback(data);
}
});
}
and then you can call it like this:
ajax_test("str", function(url) {
//do something with url
});
Here is my example code for retrieving data from php, and then pass the value to a javascript global variable within ajax success function. It works for me!
var retVal = null;
function ajaxCallBack(retString){
retVal = retString;
}
function readString(filename){
$.ajax({
type: "POST",
url: "readString.php",
data: { 'fn': filename },
success: function(response){
ajaxCallBack(response);
}
});
}
PHP code (readString.php):
<?php
$fn = $_POST['fn'];
$file = fopen("path/".$fn.".record","r");
$string = fread($file,filesize("path/".$fn.".record"));
fclose($file);
echo $string;
?>
However, as $.ajax() sent requests asynchronously, which means it may return before the success callback runs, you should not rely on it runs sequentially and return the value by itself. Therefore, here we assign php response value to global value in callback function.
I am trying to write simple function that checks to see if a designer name exists in the database. I am using jQuery's ajax function to try to do this:
function checkDesignerName(name)
{
var designer_name = $('input[name="name"]').val();
var designer_exists = false;
var temp = $.ajax( { type: "GET",
url: "/api/check_brand_exists/",
data : {name : designer_name },
success: function(data) {
designer_exists = $.parseJSON(data);
return designer_exists;
}}).statusText;
return designer_exists;
}
I have read about javascript scoping, and but still can't seem to find my bug, which is checkDesignerName always returns false. Do I need to use a closure for this function to work correctly?
Thanks
It's the nature of AJAX which is asynchronous that you seem to have troubles with understanding.
At this stage:
return designer_exists;
your AJAX call hasn't yet finished. It's only inside the success callback, which happens much later, that you can use the results. You cannot have a function which returns some result and this result depends on an AJAX call. You can only exploit the results of an AJAX call iniside the success callback:
function checkDesignerName(name)
{
var designer_name = $('input[name="name"]').val();
$.ajax({
type: "GET",
url: "/api/check_brand_exists/",
data : { name : designer_name },
success: function(data) {
var designer_exists = $.parseJSON(data);
// Here and only here you know whether this designer exists
alert(designer_exists);
}
});
}
You could of course perform a synchronous call to the server which is something totally not recommended as it will freeze the client browser and piss the user off your site during the AJAX request by setting the async: false flag:
function checkDesignerName(name)
{
var designer_name = $('input[name="name"]').val();
var designer_exists = false;
$.ajax({
type: "GET",
url: "/api/check_brand_exists/",
async: false,
data : { name : designer_name },
success: function(data) {
designer_exists = $.parseJSON(data);
}
});
return designer_exists;
}
I am mentioning this just for completeness of the answer, not as something that you should ever be doing.
Now because it seems that you are doing some kind of validation logic here, here's what I would recommend you as an ultimate solution: the jquery.validate plugin. It has this great remote rule support that will do exactly what you need here.
$.ajax is a async call. It means the statement return designer_exists gets executed even before success function is executed. That is the reason it always returns false.
your success function don't see designer_exists variable
return action runs before success function will run
You may run sync request or redesign code to callbacks logic.
For sync request your code will be:
var designer_exists = false;
function checkDesignerName(name)
{
designer_exists = false;
var designer_name = $('input[name="name"]').val();
$.ajax( { async:false,
type: "GET",
url: "/api/check_brand_exists/",
data : {name : designer_name },
success: function(data) {
designer_exists = $.parseJSON(data);
}}).statusText;
return designer_exists;
}
As Dimitrov correctly noted it's asynchronous. If you want to encapsulate the ajax call within the function you could pass in the success callback.
function checkDesignerName(name, successCallback)
and then you assign it to the jQuery ajax success function.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
The function I called inside jquery returns undefined. I checked the function and it returns correct data when I firebugged it.
function addToPlaylist(component_type,add_to_pl_value,pl_list_no)
{
add_to_pl_value_split = add_to_pl_value.split(":");
$.ajax({
type: "POST",
url: "ds/index.php/playlist/check_folder",
data: "component_type="+component_type+"&value="+add_to_pl_value_split[1],
success: function(msg)
{
if(msg == 'not_folder')
{
if(component_type == 'video')
{
rendered_item = render_list_item_video(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
}
else if(component_type == 'image')
{
rendered_item = render_list_item_image(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
}
}
else
{
//List files from folder
folder_name = add_to_pl_value_split[1].replace(' ','-');
var x = msg; // json
eval('var file='+x);
var rendered_item;
for ( var i in file )
{
//console.log(file[i]);
if(component_type == 'video')
{
rendered_item = render_list_item_video(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
}
if(component_type == 'image')
{
rendered_item = render_list_item_image(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
}
}
}
$("#files").html(filebrowser_list); //Reload Playlist
console.log(rendered_item);
return rendered_item;
},
error: function()
{
alert("An error occured while updating. Try again in a while");
}
})
}
$('document').ready(function()
{
addToPlaylist($('#component_type').val(),ui_item,0); //This one returns undefined
});
The function addToPlaylist doesn't return anything. It makes an asynchronous request, which eventually executes a callback function, which returns something. The original addToPlaylist function is long done and returned by the time this happens though, and the callback function returns to nobody.
I.e. the success: function(msg) { } code executes in a different context and at a later time than the surrounding addToPlaylist function.
Try this to see it in action:
function addToPlaylist() {
$.ajax({
...
success : function () {
alert('second'); // comes after 'first'
return null; // returns to nobody in particular
}
});
alert('first'); // comes before 'second'
return 'something'; // can only return here to caller
}
You're making your request via AJAX, which by definition is asynchronous. That means you're returning from the function before the AJAX request completes. In fact, your return statement is meaningless as it returns from the callback function, not your addToPlaylist function.
You have a couple of choices. The first one is better.
First, you can work with the asynchronous nature of the AJAX request and pass a callback into your addToPlaylist method (much like you're passing in the anonymous callback to the ajax function) and have the AJAX callback, call that function instead of doing the return. That way your request completes asynchronously and doesn't lock up your browser while it's going on.
function addToPlaylist(component_type, add_to_pl_value, pl_list_no, cb )
{
...yada yada yada...
$.ajax({
...
success: function(data) {
...
if (cb) {
cb.apply(this, rendered_item );
}
}
});
}
Second, you can add the option aSync: false to the ajax call. This will force the AJAX call to run synchronously (essentially it just loops until the call returns then calls your callback). If you do that, you need to capture a local variable in your addToPlaylist function inside the callback and assign the value(s) to it from the callback. At the end of the addToPlaylist function, return this variable as the result.
function addToPlaylist(component_type, add_to_pl_value, pl_list_no )
{
...yada yada yada...
var result = null;
$.ajax({
aSync: false,
...
success: function(data) {
...
result = rendered_item;
}
});
return rendered_item;
}
I agree with deceze. What you need to do is perform the necessary action(s) for rendered_item in the success function rather than relying on getting something back from addToPlayList().
I have this function that makes an ajax call. I'm describing the problem in the last chunk of code comments.
function doop(){
var that = this;
var theold = "theold";
var thenew = "thenew";
$.ajax({
url: 'doop.php',
type: 'POST',
data: 'before=' + theold + '&after=' + thenew,
success: function(resp) {
if(resp == 1) {
$(that).siblings('.theold').html(thenew);
}
}
});
// I have some code here (out of the ajax) that **further** changes
// the .theold's html beyond what it was changed inside ajax success
// but the change depends on whether the resp (inside the success
// function) returned 1 or not, so this code out here depends on the ajax
// so it looks like I have to turn this ajax call into a sync ajax
return false;
}
Based on the problem as described in the code comments, what changes are best for this situation?
You need to set async: false for synchronous requests like this:
function doop(){
var that = this;
var theold = $(this).siblings('.theold').html();
var thenew = $(this).siblings('.thenew').val();
$.ajax({
async: false,
url: 'doop.php',
type: 'POST',
data: 'before=' + theold + '&after=' + thenew,
success: function(resp) {
if(resp == 1) {
$(that).siblings('.theold').html(thenew);
}
}
});
// some other code
return false;
}
see here for details
Either set the Ajax call to synchronous as stefita pointed out, or just move your code into the success callback. Why can't you do this? Even if it's another Ajax call it still can be done - you can nest them. With the information given by you so far (I can't see the problematic code, nor I have enough domain knowledge about your project) I don't see a problem, really.
I prefer to use callback to do the job because it achieves exactly the same result without actually making it synchronous. I use success:callback and then pass in the callback as a parameter.
function getData(callback) {
$.ajax({
url: 'register/getData',
data: "",
dataType: 'json',
success: callback
});
}
I then call this function like this:
getData(function(data){
console.log(data); //do something
});
I want to assign value to global variable in javascript from jquery ajax function.
var trueFalse;
$.ajax({
type: "GEt",
url: "url",
data: "text=" + $("#text").val(),
success: function(msg) {
if(msg.match(/OK/) != null) {
trueFalse = "true";
}
else {
trueFalse = "false";
}
}
});
return trueFalse;
here i need the value of trueFalse from success function.
thanks
v.srinath
Your code won't work because the line return trueFalse; executes before the success function runs, since it is called as the result of an asynchronous (as in the A in Ajax) HTTP request. You would need to pass in a callback function to this code, and invoke that in the success function:
function getWithCallback(val, callback) {
var scope = this;
$.ajax({
type: "GET",
url: "url",
data: "text=" + val,
success: function(msg) {
callback.call(scope, msg.match(/OK/) || false);
}
});
}
getWithCallback($("#text").val(), function(result) {
if (result) {
// Do something
}
});
You could try this to validate a form on submit:
var validating = false;
var valid = false;
$('#myform').submit(function(event) {
if (validating) {
return false;
}
if (valid) {
return true;
}
var form = this;
validating = true;
getWithCallback($('#text').val(), function(result) {
if (result) {
valid = true;
form.submit();
}
validating = false;
});
return false;
});
You might also want to look at the jQuery Validation plugin
If you really can't change the application logic, then you have to create a "synchronous" ajax request (by setting async:false in $.ajax options), then it will wait until the "GET" has executed and only then return the value to the caller.
Otherwise, you should rewrite the code so that the success function calls back into some callback function that it can now proceed with whatever has to be done.
Since you are doing this on form.onsubmit, you cannot do an async request. The browser won't know that it should wait until the async request is finished. The benefit of using async is that it does not lock up your scripts/browser, but in this case that is actually what you want.