Stacking multiple AJAX requests on success (jQuery) - javascript

I'm just testing a local application and wanted to make something like this:
Click button, that's easy.
Perform AJAX request and create a database table.
Once the table is created, perform another series of AJAX requests and populate the table according to some parameters gotten from a series of select boxes.
"Animate" the whole thing using a progress bar.
Surprisingly, everything is working fine (apart the last point), but I'm getting some troubles.
The table gets created and populated but, for some reasons, the very last AJAX requests doesn't fire correctly, since it's not passing a parameter correctly.
My ajax requests are ALL asyncronous, if I set them syncronous the whole thing will freeze, but all the requests are executed correctly, even the very last one.
For instance, let's say that I don't want to use asyncronous requests in order to DON'T freeze the page and be able to show a progress bar.
The questions are the following:
Is it possible to call the same script twice?
Is there an efficient way to avoid ajax requests executing before other ajax requests?
After reading a whole bunch of topics here in stackoverflow, I edited my code and tried to:
use jQuery.AJAX prototype instead of jQuery.POST
Set everything asyncronously, in order to don't freeze the page and be able to handle a progress bar
perform the very next AJAX request into the "success" callback of the parent AJAX request.
At this point, I still have another question:
By stacking AJAX requests, is it actually TRUE that everything executed into the "success" callback will be executed AFTER the ajax requests has completed?
This is what I'm performing:
$.ajax({
type: "POST",
url: '../libs/php libraries/agenda.php',
data: {'action':'create>agenda', 'sqlname': createInfo},
processData: true,
dataType: "json",
timeout: 60000,
async: true,
success: function(res) {
$('#popup_content').append(res.log);
var dateList = new Array();
var dateObj = new Date();
var m = dateObj.getMonth();
var Y = dateObj.getFullYear();
for (var i = 1; i <= 31; i++) {
dateList.push(i+"/"+m+"/"+Y);
}
for (var i = 0; i < dateList.length; i++) {
var rs = false;
$.ajax({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'validate>date', 'date': dateList[i]},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(x) {
$('#popup_content').append(x.log);
if (x.res == 'true') {
rs = dateList[i];
}
if (rs != false) {
$.ajax({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'create>day', 'date': rs, 'sqltable': createInfo},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(newResult) {
console.log(newResult.res);
$('#popup_content').append(newResult.log);
}
});
}
}
});
}
}
});
the first AJAX request executes correctly, the second one does too, but in the third one (the one with data: {'action':'create>day', 'date': rs, 'sqltable': createInfo}) is getting fired but is missing the parameter rs defined above.
Also, to be clearer, rs is a temporary variable I've defined when I was trying to make the requests outside the "success" callback and when using $.when and $.done, in this case the variable rs is useless, but It won't change anything.
Again, as said above, the whole thing works using a syncronous request, but doesn't by using an asyncronous one.
Moreover, I'm just going to use this script locally, so delays or every problematic related to delays caused by servers and client are not important.
Is there any reason for the last request to don't work with an asyncronous request? if so is there a valuable solution for this case? I've also checked the topics about the queue, but it didn't solve my problem either. For some reasons, asyncronously, the last AJAX requests get just partially fired, since the variable rs is not getting passed correctly.

One solution is to use queue() function. This way you can execute as many functions as you want
var ajaxQueue = $({});
$.ajaxQueue = function(date, ajaxOpts) {
// queue the method. a second call wont execute until this dequeues
ajaxQueue.queue(function(next) {
// for this example I serialize params, but you can save them in several variables
// and concat into ajaxOpts.data
var params = method_that_get_params_and_serialize_them();
ajaxOpts.data = params;
ajaxOpts.complete = function() {
next();
};
$.ajax(ajaxOpts);
});
};
Then your functions have no need of shared vars, with the concurrency conflicts that it causes.
It should be like this:
$.ajax({
type: "POST",
url: '../libs/php libraries/agenda.php',
data: {'action':'create>agenda', 'sqlname': createInfo},
processData: true,
dataType: "json",
timeout: 60000,
async: true,
success: function(res) {
$('#popup_content').append(res.log);
var dateList = new Array();
var dateObj = new Date();
var m = dateObj.getMonth();
var Y = dateObj.getFullYear();
for (var i = 1; i <= 31; i++) {
dateList.push(i+"/"+m+"/"+Y);
}
for (var i = 0; i < dateList.length; i++) {
processDate(dateList[i]);
}
}
});
function processDate(date){
$.ajaxQueue({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'validate>date', 'date': date},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(x) {
$('#popup_content').append(x.log);
if (x.res == 'true') {
$.ajax({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'create>day', 'date': date, 'sqltable': createInfo},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(newResult) {
console.log(newResult.res);
$('#popup_content').append(newResult.log);
}
});
}
}
});
};
}

Related

How to get multiple ajax request with promises

I'm trying to get a single image from each ajax request and append it to a li box container, the first ajax returns a list of 20 objects, with name and a url
$.ajax({
url: "http://pokeapi.co/api/v2/pokemon/",
dataType: "json",
method: "GET",
cache: false,
success: function(data) {
for (var i = 0; i<data.results.length ;i++){
$("#root ul").append('<li class="box"></li>');
$("li").eq(i).append('<h2>' + data.results[i].name +'</h2>');
}
setPkmImage(data.results);
console.log(data);
},
error: function(data) {
console.log("Error");
}
});
The problem starts when I try to make a call for each of those objects to request an image, it works with the async: false, but i don't want to do it that way since it takes a lot of time to load all the images.
function setPkmImage(res){
for (var i = 0; i < res.length; i++) {
var promise = $.ajax({
url: res[i].url,
dataType: "json",
method: "GET",
cache: false,
//async: false,
promise.done( function(data) {
console.log(data);
$("#root ul");
$("li").eq(i).append('<img src="' + data.sprites.front_default+ '"/>');
});
promise.fail( function(data) {
console.log("Error");
});
});
}
}
I'm trying to use promises but I don't know exactly how to structure it
Two major problems, one is syntax and the other is you need a closure loop
First the $.ajax is not closed properly.
Should look more like:
var promise = $.ajax({
url: res[i].url,
dataType: "json",
method: "GET",
cache: false
});
promise.done(...
promise.fail(...
As for the closure loop, i won't be what you want it to be inside the ajax callbacks because the for loop will have been completed before the data for requests is returned. Thus i will be at it's maximum by then
Try changing the for loop to $.each which creates a closure
$.each(res, function(i, item){
var promise = $.ajax({
url: item.url,
dataType: "json",
method: "GET",
cache: false
});
promise.done(...
promise.fail(...
})
I usually use the next solution. After first request is done, I've insert to dom img with url (url is come from request) and browser will load images automatically.

How to send array in AJAX using JSON

I am fairly new to JS and AJAX, and for some reason I can not send my dynamically generated and read data via AJAX. How do I properly send an array via AJAX to PHP script?
I have tried following the instructions but I can not get the AJAX to send the data. The first try was a complete bust, the second gets error:
Uncaught TypeError: Illegal invocation
but it seems to originate from the JS-library instead of my code (though the code is most probably the reason for it!) and I do not know what to do with it.
//first thing I tried
var i = 1, j = 0, cu = [], cu2 = [];
while (i <= tilit ) {
cu[j] = document.getElementById("til_nro_"+i);
console.log(cu[j].value);
i++;
}
var dynamic_account_value = JSON.stringify(cu);
jQuery.ajax({
type: "POST",
url: 'http:mysite.php',
dataType: 'json',
data: { dynamic_account_count:tilit, db:cu , id:id, result:dynamic_account_value
}
});
//2nd thing I tried
var i = 1, j = 0, cu = [], cu2 = [];
while (i <= tilit ) {
cu[j] = document.getElementById("til_nro_"+i);
cu2.push(JSON.parse(cu[j].value));
i++;
}
var tilinrot_lisa = JSON.stringify(cu2);
jQuery.ajax({
type: "POST",
url: 'http:mysite.php',
dataType: 'json',
data: { dynamic_account_count:tilit, db:cu , id:id, result:tilinrot_lisa
}
});
First, give them something that makes selection easier, like a common class. Second, use jquery serialize
$.ajax({
url : "foo",
data : $(".bar").serialize(),
success : function(response) {}
})
Try this code snippet, Try to send just one variable then go for another & use content type.
u can use //console.log(JSON.stringify(cu)); to view what's inside.
jQuery.ajax({
type: 'post',
dataType: 'json',
data: {your_var:JSON.stringify(cu)},
contentType: "application/json"
});

Ajax asynchronous response not loading into div

Here is what bothering me. My code is running on document.ready. I need the request to be asynchronous, meaning async: true
for (var i = 0; i < totalGraphs; i++) {
var kpiId = kpiIds[i];
jQuery.ajax({
type: 'POST',
url: graphUrl,
data: "kpiId="+kpiId+"&divId="+(i+1),
async: true, //if false things are working fine
cache:false,
success: function(response){
document.getDocumentById("graph" + (i + 1)).innerHTML("hello");
},
error:function(XMLHttpRequest, textStatus, errorThrown) {
}
});
}
This request does not put hello in my graphX divs, but whenever i put async: false things are working fine. I really need the request to be asynchronous.
Thanks in advance for any help.
Try this...
for (var i = 0; i < totalGraphs; i++){
(function ajaxCall(index) {
var kpiId = kpiIds[index];
jQuery.ajax({
type: "POST",
url: graphUrl,
data: {
kpiId : kpiId,
divId : index + 1
},
async: true, //if false things are working fine
cache: false,
success: function(response) {
document.getDocumentById("graph" + (index + 1)).innerHTML("hello");
},
error: function(XMLHttpRequest,textStatus,errorThrown) {}
});
})(i);
}
I've wrapped the ajax call in an anonymous function so that the value of i will never change, relative to the ajax call.
I'm guessing the i count is getting mixed up in your loop when success is returned. success will return after the loop has run through and thus this will give an unexpected result.
Can you return the i value that went sent in data in your response then use this in your getDocumentById method? I'm guessing this would fix your issue.
New code to try:
for(var i=0;i<totalGraphs;i++){
jQuery.ajax({
type: 'POST',
url: graphUrl,
data: { kpiId: kpiIds[i], divId: (i+1) },
async: true, //if false things are working fine
cache:false,
success: function(response){
document.getDocumentById("graph" + response.count).innerHTML("hello");
},
error:function(XMLHttpRequest,textStatus,errorThrown){}
});
}
First of all, you are running an ajax call inside a loop. This will be okay if you've turned off the async. But since you've turned on the async, the loop doesn't wait for the ajax to finish its work.
The best thing to do would be to get the values to a global variable using the inner loop ajax and then use the variable to draw the graph later.

backbone javascript setTimeOut method

im have a problem with method setTimeOut that call the function self and set a delay, the function should be called again and again after every request is done but it only runs once. It works without using backbone.js tho, don't know it doesnt work after integration with backbone.js. Any help is appreciated!
So this is a function in client that runs a GET request gets data from server, the request runs in a time interval(decided in the server), as soon as a data comes in, client gets it and the request runs again after.
getRequest:function() {
var XHR = $.ajax({
url: '/nextdocument',
type: 'GET',
async: true,
cache: false,
timeout: 11000,
success:function(data) {
var name = data.description;
var price = data.price;
console.log("read--> " + name + price);
setTimeout("this.getRequest", 1000);
if (data.ok == "true") {
data["ok"] = data.ok;
$.ajax(
{
url: "/customerdone",
data: JSON.stringify(data),
processData: false,
type: 'POST',
contentType: 'application/json'
}
)
}else{
//no document if no read in
console.log("error--> " + data.errorMessage)
}
}
})
return XHR;
}
The problem is that you're using "this" in your setTimeout call. You can't do this because "this" will be the global object when the timer executes the function you're trying to reference.
like others have suggested, you need to pass an actual function to your timer, not a string. then you can reference whatever function from whatever object you want.
probably, the function getRequest isn't being called. This is, as far as I think, because you are sending a string -- "this.getRequest" to the setTimeout function. As a rule of thumb, never pass string to this, pass functions. Although, it might be perfectly ok in some situations (i'd never recommend it anyway), here 'this' might be causing trouble. Use something like this:
getRequest:function() {
var fn = arguments.callee;
var XHR = $.ajax({
url: '/nextdocument',
type: 'GET',
async: true,
cache: false,
timeout: 11000,
success:function(data) {
var name = data.description;
var price = data.price;
console.log("read--> " + name + price);
setTimeout(fn, 1000);
if (data.ok == "true") {
data["ok"] = data.ok;
$.ajax(
{
url: "/customerdone",
data: JSON.stringify(data),
processData: false,
type: 'POST',
contentType: 'application/json'
}
)
}else{
//no document if no read in
console.log("error--> " + data.errorMessage)
}
}
})
return XHR;
}

Modifying jQuery $.ajax() success method during request

In the web app I am working on there is potential for very long running ajax queries.
I'm using jQuery's $.ajax method to do something like:
this._xhr = jQuery.ajax({
type: "GET",
url: "/path/to/service",
data: "name=value",
success: function(data, message){
// handle a success
},
dataType: "json"
});
Is there a way to modify the success callback after this._xhr.readyState = 2 (loaded) and before this._xhr.readyState = 4 (completed)
I tried modifying this._xhr.onreadystatechange but found that jQuery does not define onreadystatechange.
The abort method sounds like the best option to me.
I don't know much about the ajax method internals, but I can think of a few ways to do what you want. Both involve global state and would break if it's possible for your user to send a second request before the first has finished, so I'm not sure I recommend them.
First, you could keep a reference to the method that does your success work, and change it:
MySuccessMethod = function(d, m) { /* handle a success */ };
this._xhr = jQuery.ajax({
type: "GET",
url: "/path/to/service",
data: "name=value",
success: function(data, message){ MySuccessMethod(data, message); },
dataType: "json"
});
// later...
// user cancels request, so change the success method
MySuccessMethod = function(d, m) { /*print a simple message*/ }
Alternatively, you could just put all the logic in the one success method, and use a global flag to determine what to do:
success: function(data, message){
if (RequestHasBeenCancelled) {
//display a simple message
}
else {
// handle a success
}
},

Categories