This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I'm trying to successfully pass the result to another function and it's simply returning an undefined value:
function tagCustomer(email, tags) {
var o = new Object();
o.tags = tags;
o.email = email;
o.current_tags = getCustomerTags(email);
o.new_tags = tags;
console.log(o);
return true;
}
function returnData( data ) {
return data;
}
function getCustomerTags(email) {
$.ajax({
url: "xxx.io/index.php",
type: "POST",
dataType: "json",
data: {email: email, "action": "getCustomerTags"},
contentType: "application/x-www-form-urlencoded; charset=utf-8",
success: function (data) {
returnData( data );
return data;
}
});
}
o.current_tags should get the result of getCustomerTags.
You should change getCustomerTags to something like this since it makes an asynchronous request:
function getCustomerTags(email) {
return $.ajax({
url: "xxx.io/index.php",
type: "POST",
dataType: "json",
data: {
email: email,
action: "getCustomerTags"
},
contentType: "application/x-www-form-urlencoded; charset=utf-8",
});
};
and then use it like this:
getCustomerTags(email).done(function(data) {
console.log(data)
});
You normal approach will not work here, because you try return before response comes back from server. Instead you use callback function or promises.
You are dependent on ajax response to return data from the function. But ajax by default is asynchronous and does not wait for the server response. therefore your function does not return anything.
Try this (It's not good for UI, but with your current code it will work, also, look at the "BETTER PRACTICE" on the bottom of my answer):
function getCustomerTags(email) {
var result = null;
$.ajax({
url: "xxx.io/index.php",
type: "POST",
dataType: "json",
async: false,
data: {
email: email,
"action": "getCustomerTags"
},
contentType: "application/x-www-form-urlencoded; charset=utf-8",
success: function (data) {
result = data;
}
});
return result;
}
The reason your code didn't work, is that the $.ajax success function is returning the data var, but getCustomerTags isn't returning anything. Also, pay attention to the "async: false", because if you use it as async, the function will return null because it will return before the ajax completes.
BETTER PRACTICE
The ajax function has a callback (success), USE IT!
design your code not as a method waiting for the ajax request result, but as an ajax request that does something upon it's completion!
EXAMPLE
function tagCustomer(email, tags, data) {
var o = new Object();
o.tags = tags;
o.email = email;
o.current_tags = data
o.new_tags = tags;
console.log(o);
return true;
}
function getCustomerTags(email, tags) {
$.ajax({
url: "xxx.io/index.php",
type: "POST",
dataType: "json",
data: {email: email, "action": "getCustomerTags"},
contentType: "application/x-www-form-urlencoded; charset=utf-8",
success: function (data) {
tagCustomer(email, tags, data);
}
});
}
If you have any further questions, don't hesitate to comment.
Related
I am working on a flask application and there is this javascript function associated with a form
function applyQueries() {
// does some things
if(currentCatalog != ''){
addCatalogFilters(currentCatalog);
}
$.ajax({
type: 'POST',
url: "/applyQueries",
contentType: "application/json",
success:function(response){
// does some stuff here
})
}
The addCatalogFilters() function is also an ajax call. Both these calls change some variables in the python side of things. What I want to know is if the first ajax call (in addCatalogFilters), is guaranteed to execute and return before the second one. I am ending up with weird results that appear to be race conditions based on the order the ajax calls execute. Is this possible with code structured like this? Also if so, how can I fix it?
// Add user catalog filters
function addCatalogFilters() {
catalog = currentCatalog;
formData = new FormData(document.getElementById('catalogFilterForm'));
$.ajax({
type: 'POST',
url: "/addCatalogFilters",
data: formData,
processData: false,
contentType: false,
success: function (response){
document.getElementById(catalog + 'close').style.display = 'block';
document.getElementById(catalog + 'check').style.display = 'none';
addBtns = document.getElementsByClassName("addBtn");
removeBtns = document.getElementsByClassName("removeBtn");
for (i = 0; i < addBtns.length; i++) {
addBtns[i].style.display = "none";
removeBtns[i].style.display = "inline-block";
}
}
})
};
You can ensure with success function of ajax. First call a ajax (let's say ajax1) then call another ajax call within the success function of first ajax call (ajax1 success function).
addCatalogFilters(currentCatalog)
{
$.ajax({
type: 'POST',
url: "/the-post-usl",
success:function(response){
$.ajax({
type: 'POST',
url: "/applyQueries",
contentType: "application/json",
success:function(response){
// does some stuff here
});
})
}
function applyQueries() {
// does some things
if(currentCatalog != ''){
addCatalogFilters(currentCatalog);
}
}
It may not be the optimum way. But guarantee one ajax call is complete before calling another.
You could try using async/await like this:
async function applyQueries() {
if(currentCatalog !== ''){
const filtersAdded = await addCatalogFilters(currentCatalog);
}
// Perform AJAX call
}
By usinc async/await, your code will wait until the addCatalogFilters() function has resolved. However, for this to work, the addCatalogFilters() function should be async with a return value. Something like this:
async function addCatalogFilters(catalog){
// Ajax call
$.ajax({
type: 'POST',
url: "foo",
contentType: "application/json",
success:function(response){
return true
})
}
Depending on how applyQueries is called, you may need to have an await or .then where you call it. Note that you can also use "result = await addCatalogFilters(currentCatalog)" to put the ajax result into a variable result that you can work with and pass to your $.ajax call in applyQueries. I don't know the nature of your code, so I can't make any direct suggestions.
async function applyQueries() {
// does some things
if(currentCatalog != ''){
// await on the returned Promise-like jqXHR (wait for ajax request to finish)
// recommend assigning awaited result to a variable and passing to next $.ajax
await addCatalogFilters(currentCatalog);
}
return $.ajax({
type: 'POST',
url: "/applyQueries",
contentType: "application/json",
success:function(response){
// does some stuff here
})
}
// Add user catalog filters
function addCatalogFilters() {
catalog = currentCatalog;
formData = new FormData(document.getElementById('catalogFilterForm'));
// return the Promise-like jqXHR object: https://api.jquery.com/jQuery.ajax/#jqXHR
return $.ajax({
type: 'POST',
url: "/addCatalogFilters",
data: formData,
processData: false,
contentType: false,
success: function (response){
document.getElementById(catalog + 'close').style.display = 'block';
document.getElementById(catalog + 'check').style.display = 'none';
addBtns = document.getElementsByClassName("addBtn");
removeBtns = document.getElementsByClassName("removeBtn");
for (i = 0; i < addBtns.length; i++) {
addBtns[i].style.display = "none";
removeBtns[i].style.display = "inline-block";
}
}
})
};
You can use async/await. However, as no one has mentioned, I would like to demonstrate how you can accomplish this with Promise.
Lets define two functions:
function first_function(data) {
return new Promise((resolve, reject) => {
let dataSet = [[]];
let response;
$.ajax({
type: "POST",
url: 'example.com/xyz',
async: false,
data: data,
success: function (value) {
response = value;
dataSet = JSON.parse(response);
resolve(dataSet)
},
error: function (error) {
reject(error)
},
processData: false,
contentType: false
});
})
}
function second_function(data) {
return new Promise((resolve, reject) => {
let dataSet = [[]];
let response;
$.ajax({
type: "POST",
url: 'example.com/abc',
async: false,
data: data,
success: function (value) {
response = value;
dataSet = JSON.parse(response);
resolve(dataSet)
},
error: function (error) {
reject(error)
},
processData: false,
contentType: false
});
})
}
Now you can make sure that second_function() gets called only after the execution of ajax request in first_function() by following approach:
first_function(data)
.then(dataSet => {
//do other things
second_function(dataSet)
.then(dataSet2 => {
////do whatever you like with dataSet2
})
.catch(error => {
console.log(error);
});
});
I have a specific requirement with nested ajax calls. I am trying to set a globally accessible variable inside success of one ajax call and this ajax call is being invoked inside success of another ajax call. Eventually the parent success method of parent ajax call utilizes the global variable to perform further operations. The problem is that the value of global variable always remains blank. It works if I make the second ajax request as async:false; but this solution defeats the very purpose of using ajax in the first place.
Let me share a small sample code to illustrate my problem:
//global variables
var xURL = "https://sampleurl.com";
var glblID = "";
//first ajax call
$.ajax({
url: url1,
data: data1,
type: "POST",
contentType: "application/json",
success: function (msg) {
//some js code here
//second ajax call
FetchID();
//more js code here
if(glblID != "")
{
window.location.href = xURL + "?id=" + glblID
}
else
{
window.location.href = xURL;
}
}
});
function FetchID()
{
$.ajax({
url: url2,
data: data2,
type: "POST",
contentType: "application/json",
success: function (data) {
glblID = data.d;
}
});
}
As of jQuery 1.5 implement the Promise interface, giving them all
the properties, methods, and behavior of a Promise
//first ajax call
$.ajax({
url: url1,
data: data1,
type: "POST",
contentType: "application/json"
}).then(function (msg) {
//second ajax call
FetchID().then((data) => {
var glblID = data.d;
if (glblID != "") {
//do something with glblID
} else {
//do something else
}
});
});
function FetchID() {
return $.ajax({
url: url2,
data: data2,
type: "POST",
contentType: "application/json"
});
}
I am working on a real estate web app in ASP.NET MVC. My problem is in my Reservations section.
I am using AJAX to post in a Controller which returns a JSONResult. Here is my code:
Controller
[HttpPost]
public JsonResult SubmitReservation(ReservationViewModel rvm)
{
return Json(rvm, JsonRequestBehavior.AllowGet);
}
Main AJAX
var rvm = new ReservationViewModel();
getBuyerInfo(rvm.SelectedBuyerID, clientCallback);
getSiteInfo(rvm.SelectedSiteID, siteCallback);
getUnitInfo(rvm.SelectedUnitID, unitCallback);
$.ajax({
url: "/Reservations/SubmitReservation",
data: JSON.stringify(rvm),
type: "POST",
dataType: "json",
contentType: "application/json",
success: function () {
console.log(clientData);
console.log(siteData);
console.log(unitData);
//Assignment of data to different output fields
//Client Data
$('#clientName').html(clientData.FullName);
$('#clientAddress').html(clientData.Residence);
$('#clientContact').html(clientData.ContactNumber);
//Site Data
$('#devSite').html(siteData.SiteName);
$('#devLoc').html(siteData.Location);
////House Unit Data
$('#unitBlock').html(unitData.Block);
$('#unitLot').html(unitData.Lot);
$('#modelName').html(unitData.ModelName);
$('#modelType').html(unitData.TypeName);
$('#lotArea').html(unitData.LotArea);
$('#floorArea').html(unitData.FloorArea);
$('#unitBedrooms').html(unitData.NumberOfBedrooms);
$('#unitBathrooms').html(unitData.NumberOfBathrooms);
$('#unitPrice').html(unitData.Price);
$('#reservationDetails').show();
alert("Success!");
},
error: function (err) {
alert("Error: " + err);
}
});
Functions for fetching data
function getBuyerInfo(id, cb) {
$.ajax({
url: "/BuyersInformation/GetBuyerByID/" + id,
type: "GET",
contentType: "application/json",
dataType: "json",
success: cb
});
}
function getSiteInfo(id, cb) {
$.ajax({
url: "/Sites/GetSiteByID/" + id,
type: "GET",
contentType: "application/json",
dataType: "json",
success: cb
});
}
function getUnitInfo(id, cb) {
$.ajax({
url: "/HouseUnits/GetUnitByID/" + id,
type: "GET",
contentType: "application/json",
dataType: "json",
success: cb
});
}
function ReservationViewModel() {
var buyerId = $('#SelectedBuyerID').val();
var siteId = $('#SelectedSiteID').val();
var unitId = $('#SelectedUnitID').val();
var rsvDate = $('#ReservationDate').val();
var me = this;
me.ReservationDate = rsvDate;
me.SelectedBuyerID = buyerId;
me.SelectedSiteID = siteId;
me.SelectedUnitID = unitId;
}
function clientCallback(result) {
clientInfo = result;
clientData = clientInfo[0];
}
function siteCallback(result) {
siteInfo = result;
siteData = siteInfo[0];
}
function unitCallback(result) {
unitInfo = result;
unitData = unitInfo[0];
}
The whole code WORKS well for the second time. However, it does not work for the FIRST time. When I refresh the page and I hit Create, it returns undefined. But when I hit that button again without refreshing the page, it works well. Can somebody explain to me this one? Why does AJAX returns undefined at first but not at succeeding calls? Thanks in advance.
You are calling several ajax requests in your code, inside these functions:
getBuyerInfo(rvm.SelectedBuyerID, clientCallback);
getSiteInfo(rvm.SelectedSiteID, siteCallback);
getUnitInfo(rvm.SelectedUnitID, unitCallback);
and finally $.ajax({...}) after them, where you use results from pervious ajax calls.
Your problem is that the first ajax calls do not necessarily return results before your start the last ajax because they are all async. You have to make sure you get three responds before calling the last ajax. Use promises or jQuery when, like this:
var rvm = new ReservationViewModel();
$.when(
$.ajax({
url: "/BuyersInformation/GetBuyerByID/" + rvm.SelectedBuyerID,
type: "GET",
contentType: "application/json",
dataType: "json"
}),
$.ajax({
url: "/Sites/GetSiteByID/" + rvm.SelectedSiteID,
type: "GET",
contentType: "application/json",
dataType: "json"
}),
$.ajax({
url: "/HouseUnits/GetUnitByID/" + rvm.SelectedUnitID,
type: "GET",
contentType: "application/json",
dataType: "json"
})
).done(function ( clientResponse, siteResponse, unitResponse ) {
clientInfo = clientResponse;
clientData = clientInfo[0];
siteInfo = siteResponse;
siteData = siteInfo[0];
unitInfo = unitResponse;
unitData = unitInfo[0];
$.ajax({ ... }) // your last ajax call
});
AJAX calls are asynchronous. You last ajax call will not wait until your above 3 ajax calls finishes its work. so you can make use of $.when and .done here as below..
$.when(
getBuyerInfo(rvm.SelectedBuyerID, clientCallback);
getSiteInfo(rvm.SelectedSiteID, siteCallback);
getUnitInfo(rvm.SelectedUnitID, unitCallback);
).done(
$.ajax({
//Ajax part
})
);
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 returns a JS object. however when i assign a var to the function i get undefined. Debugging in FireBug, everything is fine, except when i try and assign the result to the var tester
here is my code...
function AllBidData(HighestBid,MinimumBid,HighestProxyBid) {
return {
HighestBid: HighestBid,
MinimumBid: MinimumBid,
HighestProxyBid: HighestProxyBid
};
}
function GetAllBidData() {
$.ajax({
type: "POST",
dataType: "json",
url: "/VehicleAuction/GetAllBidData",
data: { AuctionID: AuctionID, UserID: UserID }
}).done(function (msg) {
var BidDate = new AllBidData(msg.HighestBid, msg.MinimumBid, msg.HighestProxyBid);
return BidDate;
});
}
var tester = GetAllBidData();
//why is tester is undefined?
UPDATE & SOLUTION - So this is the way i have solved this problem - using deferred objects
function GetAllBidData() {
return $.ajax({
type: "POST",
dataType: "json",
url: "/VehicleAuction/GetAllBidData",
data: { AuctionID: AuctionID, UserID: UserID }
});
}
function AllBidData(data) {
return {
HighestBid: data.HighestBid,
MinimumBid: data.MinimumBid,
HighestProxyBid: data.HighestProxyBid
};
}
var tester = null;
tester = GetAllBidData().done(AllBidData);
It's asynchronous call. The function executes and returns value before the ajax call happen
function GetAllBidData(callback) {
$.ajax({
type: "POST",
dataType: "json",
url: "/VehicleAuction/GetAllBidData",
data: { AuctionID: AuctionID, UserID: UserID }
}).done(function (msg) {
var BidDate = new AllBidData(msg.HighestBid, msg.MinimumBid, msg.HighestProxyBid);
callback(BidDate);
});
}
var tester = GetAllBidData(function(yourValue){
//do stuff here with yourValue
});
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Synchronous calls with jquery
I am trying to return a value from a function that contains an ajax call (please see code below).
The returnValue variable is undefined at the alert and when it returns. Can anyone help please?
function getLightboxImages(){
var returnValue;
jQuery.ajax({
url: "http://test.domain.com/WebService.svc/GetAllI",
data: { id: "2", hash:"MaD01" },
async: false,
dataType: "jsonp",
success: function (result) {
returnValue = result
}
});
alert(returnValue);
return returnValue;
}
The alert would have to be placed in the success function, as that is called when ajax returns. What you have above will send the request and then try to alert the returned value before the request is completed.
try this code, for JSONP you have to use callback function rather than success method.
$.ajax({
url: 'http://test.domain.com/WebService.svc/GetAllI',
type: 'GET',
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
jsonp: "callback",
jsonpCallback: "jsonpCallbackfunction",
error: function () {
alert("Error in Jsonp");
}
});
function jsonpCallbackfunction(responseData) {
alert(responseData);
}
http://cmsnsoftware.blogspot.com/2012/02/how-to-use-cross-domain-ajax-request.html#0
function getLightboxImages(){
var returnValue;
jQuery.ajax({
url: "http://test.domain.com/WebService.svc/GetAllI",
data: { id: "2", hash:"MaD01" },
async: false,
dataType: "jsonp",
success: function (result) {
returnValue = result
}
});
alert(JSON.stringify(returnValue));
return returnValue;
}
Cross-domain requests can only be async, as cross-domain requests rely on a dynamic script tag, which can never be synchronous and must use datatype json and the GET method.
For same domain requests, try stringifying json objects before alerting, like above!
You can't make synchronous JSONP requests.
Use a callback instead of return:
function getLightboxImages(callback) {
jQuery.ajax({
url: "http://test.domain.com/WebService.svc/GetAllI",
data: { id: "2", hash:"MaD01" },
dataType: "jsonp",
success: function (result) {
callback(result);
}
});
}
Usage:
getLightboxImages(function(result){
alert(result);
});