Setting global variable inside nested ajax calls - javascript

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"
});
}

Related

How can a guarantee one ajax call is complete before calling another?

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);
});
});

How to pass javascript variable into php function on an Ajax url?

I am trying to insert the value of parent into the "getFaculties()" function when i call the function using Ajax.
function ajaxfunction(parent)
{
$.ajax({
type: 'GET',
url: 'Connection.php?getFaculties('+parent')',
success: function(data) {
$("#selFaculty").html(data);
}
});
}
please use a proper way to pass data from ajax to php
function ajaxfunction(parent)
{
$.ajax({
type: 'GET',
url: 'Connection.php',
data: {method:'getFaculties', value:parent}
success: function(data) {
$("#selFaculty").html(data);
}
});
}
The correct syntax is
url: 'Connection.php?faculties='+getFaculties(parent),
Since that is query parameter, given a name to it.
use like this function Declaration was wrong
function ajaxfunction(parent)
{
$.ajax({
type: 'GET',
url: 'Connection.php?getFaculties='+getFaculties(parent),
success: function(data) {
$("#selFaculty").html(data);
}
});
}
Call your function first and get return value in variable and then send your ajax request.
function ajaxfunction(parent)
{
var data_in = getFaculties(parent);
$.ajax({
type: 'GET',
url: 'Connection.php?getFaculties='+data_in,
success: function(data) {
$("#selFaculty").html(data);
}
});
}

AJAX GET returns undefined on the first call, but works on the second one

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
})
);

Jquery: how to send one ajax request and save the JSON string for another calls

in my code i have the following
var response = "";
function send_ajax(){
if(response == ""){
$.ajax({
url: url
type: 'POST',
dataType: "JSON",
success: function(data){
response = data;
}
});
}
}
my problem is that send_ajax function is called several times in my script, and sometimes alot of ajax calls is send together and no need for that. so i'm searching for a solution in which if one ajax request is send other calls should wait until that function saves the data in the response var and use it.
how can i do that ?
If you set the async flag to false, no other calls are made until the first call is done.
$.ajax({
url: url
type: 'POST',
dataType: "JSON",
async: false,
success: function(data){
response = data;
}
});
if(response == ""){
response = 'waiting';
will do the trick, no ?
Another solution if you want the $.ajax to be async, but only allow one ajax request at any time. You could take a look at $.ajaxStart and $.ajaxStop global event
var ajaxLock = false;
$.ajaxStart(function(){ajaxLock = true;});
$.ajaxStop(function(){ajaxLock = false;});
var ajaxRequest = function(url, data) {
if (!ajaxLock) {
$.ajax({
url: url
type: 'POST',
dataType: "JSON",
async: false,
success: function(data){
response = data;
}
});
}
}

problems executing a jquery ajax call within a function

I would like to put an ajax call within a function since I use it repeatedly in multiple locations. I want a manipulated version of the response returned. Here's what I'm trying to do (greatly simplified).
a = getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
return response;
});
}
What's happening, however, is that the append function is running before "a" has been defined in the getAjax function. Any thoughts?
AJAX is asynchronous. This means that the code in the success handler is delayed until the request is successful, while the rest of the code continues as normal. You need to put the relevant code in the AJAX success handler:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
$(document.body).append('<div>'+response+'</div>');
});
}
Note that I have also optimised your body selector by using the native Javascript document.body rather than using the standard tag selector.
Edit Callback version
function getAjax(callback) {
$.ajax({
type: 'GET',
url: 'someURL',
success: callback
});
}
You can now do the code inline using a callback function:
getAjax(function(response) {
$(document.body).append('<div>'+response+'</div>');
});
or
getAjax(function(response) {
alert(response);
});
or whatever.
The code inside the anonymous function call will be processed when the AJAX request is complete.
There are two ways to taggle this. one is to use the success callback:
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
the other is to set async to false http://api.jquery.com/jQuery.ajax/:
var a;
getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
async: false,
success: function(response) {
a = response;
});
}
Important note on non async:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Why don't you return the response to another function in the success callback. This should handle your need for different responses:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
}
function AppendResponse(response) {
$('body').append('<div>'+response+'</div>');
}
One suggestion I have is to pass a trigger to the command you want to run into the AJAX function so that it will run after AJAX has received a response-
a = getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
inputText(response);
});
}
inputText(someText) {
$(document.body).append('<div>'+ someText +'</div>');
}
That way you can create if statements / other alternatives to continue to use the same AJAX command for different results
You can give a handler to the function getAjax(), but if the user needs the information for the next decision then why not wait using async: false?
function getAjax(handler) {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
handler(response);
});
};
function callGetAjax(response) {
if(response === undefined) {
getAjax(callGetAjax);
} else {
$('body').append('<div>'+response+'</div>');
}
}

Categories

Resources