I have AJAX code as mentioned below:
$("#id").click(function(e){
e.preventDefault();
$.ajax({
url: 'url1',
type: 'get',
data: {
method: 'method1',
param: id
},
datatype: 'json',
success: function(p){
let arr = [];
const obj = JSON.parse(p);
if (obj.RETVAL == true) {
var i;
for(i=0; i< 6 ; i++){
$.ajax({
url: 'url2',
type: 'post',
data: {
method: 'method2',
param: id2
},
success: function(r){
if (r>1) {
}
else{
arr.push(r); //this array will be passed in fun1
}
}
});
}
}
fun1(arr);
}
});
});
In my case what I noticed is fun1 is being called before the complete execution of code inside for loop. Like if for loop executed ones and the functions gets triggered. Because of this arr contains lesser entries. How can I call function fun1 only after complete execution of loop?
$.ajax returns a thenable.
Collect them in an array. Pass that array to Promise.all. Call fun1 when the promise returned by Promise.all resolves.
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);
});
});
This is my code:
function updateCharts() {
for (var i = 0; i < charts.length; i++) {
updateChart(charts[i]);
}
sortQueues();
}
function updateChart(chart) {
$.ajax({
type: "POST",
async: true,
data: '{id: ' + chart.Id + '}',
url: "foo/getData",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var parsedResponse = JSON.parse(response.d);
insertChartData(chart, parsedResponse);
},
failure: function (response) {
console.Log(response);
}
});
}
How can I run sortQueues() function after all charts are updated? Right now sortQueues() function is executed before insertChartData is finished (because ajax calls), and charts aren't sorted in html. Of course I don't want to have sync calls.
$.ajax returns a promise so you can capture them and use them with Promise.all.
First return the promise:
function updateChart(chart) {
return $.ajax({
then replace your loop with map so you get all the promises in an array.
var promises = charts.map(updateChart);
Then you can use the promise:
Promise.all(promises).then(array_of_results => {
// all ajax requests recieved at this point
});
I'm having an error when using several ajax calls, I put this in an array and I need capture when finish all.
My code is this:
var userId=[1,2,3];
var ajaxR = [];
for (var us in userId) {
var usId = userId[us];
ajaxR.push($.ajax({
type: "GET",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "myurl",
data: { id: usId }
}));
}
$.when.apply($, ajaxR).always(function (e) {
//Here I have the error but arguments it's ok
var objects = arguments;
});
When I debbug this code I have an error in $.when function:
Uncaught TypeError: Cannot read property '0' of undefined
Update:
My complete function is it:
function UserFromWS(userId) {
var users = [];
var ajaxR = [];
for (var us in userId) {
var usId = userId[us];
ajaxR.push($.ajax({
type: "GET",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "url",
data: { id: usId }
}));
}
$.when.apply($, ajaxR).always(function (e) {
var obj = arguments;
return obj;
});
// return users;
}
The error disapear if I put return users; in end of function. But it finish returning users array empty, before return obj. I need call the function in this way:
var allUsers = UserFromWS ([1,2,3]);
The function should return obj in $.when promise.
Fist thing to check is that "userId" is being passed as an array. Then the for loop need to be modified to correctly loop the array (Why is using "for...in" with array iteration a bad idea?).
Also the function needs to return a promise:
function UserFromWS(userId) {
var users = [];
var ajaxR = [];
for (var i = 0; i< userId.length; i++) {
var usId = userId[i];
ajaxR.push($.ajax({
type: "GET",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "url",
data: { id: usId }
}));
}
return $.when.apply($, ajaxR).done(function (e) {
var obj = arguments;
return obj;
});
// return users;
}
Also you will need to wait for the result of this function:
var users = [10];
UserFromWS(users).then(function(result) { /* do stuff now */ });
Why do you save the ajax call to array, JQuery can recongnize the request by himself, and you can call the same $.ajax() many times without error.
Example:
$.ajax({
type: "GET",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "url",
data: { id: usId }
}).done(function (e) {
var obj = arguments;
return obj;
});
Or if you want to continue with your system, know that when use promise
see https://api.jquery.com/jquery.when/
I have a problem with this code.
This happens:
just launch the code from console.log I get null, if I press the update button function works.
why is this happening?
how do I fix?
var urljson = "data_json.php";
var data = null;
var jqXHR = $.ajax
({
type: "GET",
url: urljson,
dataType: 'json',
success: successHandler
});
function successHandler(result) {
data = result;
}
function update(){
var jqXHR = $.ajax
({
type: "GET",
url: urljson,
dataType: 'json',
success: successHandler
});
function successHandler(result) {
data = result;
}
}
$(document).ready(function(){
console.log(data) //// null
});
document.getElementById('update').addEventListener('click', function() {
update();
console.log(data) //// Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, other 3213… ]
});
$.ajax() returns results asynchronously. Use success handler or .then() chained to $.ajax() to process response returned from request.
function update() {
var jqXHR = $.ajax({
type: "GET",
url: urljson,
dataType: "json",
success: successHandler
});
function successHandler(result) {
data = result;
// do stuff with `data` here
console.log(data);
}
}
$(document).ready(update);
jsfiddle https://jsfiddle.net/89jkzzyk/
When the page loads, update() is not getting called, thus data is null. Add your function call to $(document).ready() and it should work.
So say i have multiple ajax requests that are fired at the same time through a parent function. Each ajax function has a seperate individual completion function which are unrelated to each other. If i want a further function to execute upon completion of all ajax functions, but after the completion functions specified in each individual ajax function, how would i go about this?
function ajax1(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
}
},
complete: function (data) {
function ajaxcomplete1();
},
)
};
function ajax2(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
}
},
complete: function (data) {
function ajaxcomplete2();
},
)
};
function ajaxcall() {
ajax1();
ajax2();
}
function allajaxcomplete() {
// some code to be executed on completion of all ajax requests but after individual "ajaxcomplete1" and "ajaxcomplete2" functions
}
ajaxcall();
allajaxcomplete();
$.ajax returns a jQuery Deferred object (a promise). You then just have to use $.when to call a function when all those promises are resolved:
function ajax1(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
ajaxcomplete1();
}
});
};
function ajax2(str) {
return $.ajax({
type: 'get',
data: "q=" + str,
url: 'foo.php',
success: function (result) {
//success!
ajaxcomplete2();
}
});
};
function ajaxcall() {
// store the promises (for clarity, you also could call the functions directly in the when)
var d1 = ajax1(),
d2 = ajax2();
// this function will be called only when both promises d1 and d2 are resolved
$.when(d1, d2).done(function(result1, result2){
// do stuff when both functions are done
// result1 and result2 are the result of the ajax calls inside your functions
allajaxcomplete();
});
}