Wait for ajax requests in array to be completed - ajax

I'm trying to iterate through the ID's (containing an URL) of checked checkboxes. With each checkbox, it generates an AJAX-get which does a certain action on the database. This is working, however not all AJAX-gets seem to be executed (the redirect gets executed too fast).
As adviced, I've tried to make use of '$.when.apply', however, this doesn't seem to be working. I get a 'missing ) after argument list', most certainly generated in the part where I'm pushing the ajax-get.
Is this the right way or should I try another method?
$("#marksolved").click(function () {
var ajaxrequests = [];
// Loop through checkboxes.
$('input:checked').each(function () {
// Each id of a checkbox contains an URL.
var markurl = $(this).attr('id');
// Do the request.
ajaxrequests.push($.ajax({
method: 'GET',
url: markurl,
cache: false
});
});
// Check if all requests have completed.
$.when.apply($, ajaxrequests).then(function () {
// All requests have completed. An ajax-redirect will eventually take place too fast...
alert('All actions done!');
});
});

I get a 'missing ) after argument list', most certainly generated in the part where I'm pushing the ajax-get.
ajaxrequests.push($.ajax({
method: 'GET',
url: markurl,
cache: false
});
should be:
ajaxrequests.push($.ajax({
method: 'GET',
url: markurl,
cache: false
}));
It's missing a ), like the error says.
Side note: It would probably be far more efficient to combine all of your requests into one batch request instead of having one request for each checkbox.

You can use $.ajaxStop() to have an event raised when all ajax requests have ended, or $.ajaxComplete() for when all requests have completed.

try setting the ajax async option to false
$.ajax({
method:'GET',
url: markurl,
cache:false,
async: false
});

If you know how many ajax requests you are making, you could do something like this:
var ajax_count = 0;
var ajax_checker;
var ajax_n = 3;
$('input:checked').each(function() {
...
ajaxrequests.push($.ajax({
method:'GET',
url: markurl,
cache: false,
success: function(){ ajax_count++; }
});
}
// Check if all requests have completed.
function ajax_complete() {
if (ajax_count >= ajax_n) {
clearInterval(ajax_checker);
//continue working
alert('All actions done!');
}
}
ajax_checker = setInterval(function() {ajax_complete();}, 50);

Related

Ajax wait on success before next iteration in .each loop

I have an ajax call inside a .each loop wrapped in a setInterval function.
This handles updating of many divs on a dashboard with just a few lines of code on the html page.
I am worried about server lag vs client side speed. What will happen if the server has not responded with the data before the loop moves on to the next iteration?
So, my question is, can the loop be paused until the success is executed?
Ajax call:
setInterval(function() {
$(".ajax_update").each(function(){
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&"+$(this).data('stored'), // serializes the form's elements.
success: function(data)
{
$(data[0]).html(data[1]);
}
});
});
}, 5000); //5 seconds*
</script>
I have looked into .ajaxComplete() but I dont see how to apply this as a solution.
I have also looked at turning the loop into something that calls itself like:
function doLoop() {
if (i >= options.length) {
return;
}
$.ajax({
success: function(data) {
i++;
doLoop();
}
});
}
But would that not interfere with .each? I dont understand how that would play nice with .each and looping based on my div class.
I just cant figure it out! Any help would be appreciated.
I was able to get .when working with the ajax call, but I dont understand how to make .when do what I need (stop the loop until the ajax call is done).
$(".ajax_update").each(function(){
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&"+$(this).data('stored'), // serializes the form's elements.
success: function(data)
{
$(data[0]).html(data[1]);
}
});
$.when( $.ajax() ).done(function() {
alert("Finished it");
});
});
After thinking about your question a bit, perhaps a good solution would be to put an event in place that would trigger a new set of updates with a minimum time between your dashboard updates. This would ensure that all your updates process, that we do wait a minimum time between updates and then trigger the update cycle once again. Thus if you DO encounter any delayed ajax responses you do not try another until the previous one has all completed.
I have not fully tested this code but is should do what I describe:
//create a dashboard object to handle the update deferred
var dashboard = {
update: function (myquery) {
var dfr = $.Deferred();
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&" + myquery,
success: dfr.resolve
});
return dfr.promise();
}
};
//create a simple deferred wait timer
$.wait = function (time) {
return $.Deferred(function (dfd) {
setTimeout(dfd.resolve, time);
});
};
// use map instead of your .each to better manage the deferreds
var mydeferred = $(".ajax_update").map(function (i, elem) {
return dashboard.update($(this).data('stored')).then(function (data, textStatus, jqXHR) {
$(data[0]).html(data[1]);
});
});
//where I hang my dashboardupdate event on and then trigger it
var mydiv = $('#mydiv');
var minimumDashboardUpdate = 5000;
$('#mydiv').on('dashboardupdate', function () {
$.when.apply($, mydeferred.get())
.then(function () {
$.when($.wait(minimumDashboardUpdate)).then(function () {
mydiv.trigger('dashboardupdate');
});
});
});
mydiv.trigger('dashboardupdate');

Ajax calls and JQuery: stop previuos ajax calls

In a jsp page, when a user clicks a button, an ajax call is triggered.
If the user clicks again and again the button, I would that only the last ajax call be valid and only its response be considered.
I use:
var lastRequest=null;
$('#button').click(function() {
if (lastRequest) {
lastRequest.abort();
lastRequest = null;
}
lastRequest = $.ajax({
type: "POST",
url: "MyAction.do",
success: function (response) {
response= $('<div/>').append(response);
}
});
});
With Firebug, I see that some request are aborted, but not all.
I think that if an ajax call is triggered, it's not possible to ignore the response, is it?
EDIT
If I set a var in MyAction.do and I read it in the success callback, is it possible to have a conflict in the success callback?
In case, how could I prevent that behaviour?
My experience with aborting ajax-calls is that it can be pretty random when it works.
A workaround that I've used once or twice is counters:
var lastRequest=null;
var started = 0, finished = 0;
$('#button').click(function() {
++started;
lastRequest = $.ajax({
type: "POST",
url: "MyAction.do",
success: function (response) {
//Only do stuff on the last active request
if(++finished == started)
response= $('<div/>').append(response);
}
});
});
use object.abort() to discard data that have been called by service
i have add the code as to click on a button to abort service you can try it with respect to your case :)
lastRequest = $.ajax({
type: "POST",
url: "MyAction.do",
success: function (response) {
response= $('<div/>').append(response);
}
});
});
$(document).click(function() {lastRequest.abort() });

Javascript Mootools event stop

well,i have this script that i have set up that on submit requests php file that is used to validate my input values...i have set up that when it is not validated the correct way to echo it is not validated,now i want in my request when i get response and it is the error response to stop the submit..here is the script,it does send the request and returns response but it doesnt stop the submit...
i have made it like this but now i need to pop a confirm message when it is all done,i want to stop the form from executing when message pops up and if the user clicks yes to continue with the form...i tried it like this with fireEvent but it wont work...help guys!
window.addEvent('domready', function(){
var form=document.adminForm;
form.addEvent('submit', function(e){
var success = false;
var dataString="date=" + document.getElementById("date").value + "&start=" + document.getElementById("start").value + "&end=" + document.getElementById("end").value;
var requestData = new Request ({
url: '/provjera.php',
method:'POST',
async:false,
data:dataString,
onComplete: function(responseText){
var requestData2 = new Request({
url:'/posalji.php',
method:'POST',
data:dataString,
onComplete:function(responseText){
}
});
requestData2.send();
success= responseText == 'NO ERROR';
if(responseText == 'NO ERROR'){
}else{
alert("FAIL");
}
}
});
requestData.send();
if(success){
var result=confirm("Are you sure!?");
e.stop();
if(result){
form.fireEvent("submit");
}
}else{
e.stop();
}
});
});
This won't work, it breaks the asynchronous nature of XHR (it's *A*JAX, heh).
The way it works is this:
[form]
[submit event]
\->[function]->[xhr]->[onComplete function much later]->[e.stop() not applicable]
\->[function continues and terminates]
By the time the onComplete arrives and calls .stop(), the parent function execution has exited and failed to stop the event, it has already bubbled... XHR is non-blocking!
you have 2 patterns you can do to work around that:
1. always stop event, do something extra in onComplete
essentially, whatever the XHR passes to your onComplete can let you determine the success/failure of your operation and you can call another function, fire an event or do what you need to do (eg, transition page or display validation errors on screen or whtever).
2. use sync AJAX (anti-pattern)
you can actually make your XHR blocking if you wanted to so that in this execution context you can set a variable or stop the event from the onComplete - do so by passing async: false to your Request constructor options.
I would definitely not recommend 2 unless you are doing something like username availability checker onBlur/onChange that needs to block the thread before they submit. And even then, you can do it gracefully w/o this.
edit as per request, here is an example: http://jsfiddle.net/dimitar/du5s4/
var form = document.id('adminForm');
form.addEvent('submit', function (e) {
var success = false;
// simulate a server response of two types.
this.getElement('input[name=html]').set('value', ['success','error'].getRandom());
var requestData = new Request({
url: '/echo/html/',
method: 'post',
async: false,
data: this,
onComplete: function (responseText) {
// if server returned success, don't stop the event.
success = this.response.text == 'success';
console.log(success);
}
}).send();
success || e.stop();
});
this has been tailored for the jsfiddle api for ajax testing but you get the idea. since you evalResponse, your response can also set variables - though I don't remember what the scope of evluation will be - it may be the global object and not the inner scope of the submit function.
once again, this is totally wrong, use sparringly. you need to change over to a proper event based setup.
http://jsfiddle.net/dimitar/du5s4/2/ - same thing but w/o the async hack.
var form = document.id('adminForm');
form.addEvent('submit', function (e) {
e && e.stop && e.stop();
var self = this;
// simulate a server response of two types.
this.getElement('input[name=html]').set('value', ['success','error'].getRandom());
var requestData = new Request({
url: '/echo/html/',
method: 'post',
data: this,
onComplete: function (responseText) {
// if server returned success,
// call something like form.submit();
this.response.text == 'success' && self.submit();
console.log(this.response.text);
}
}).send();
});

jQuery MouseEnter with Ajax prob?

I am having an issue with the following logic - because the ajax request runs multiple times and I only want it to run once ?
var currentItem = jQuery('#specialId .myclass');
currentItem.mouseenter(function() {
jQuery.ajax({
type: "POST",
url: "/url/data",
data: "myData=" + dataNow,
cache: false,
success: function(html) {
//do stuff
}
});
});
The problem is that I have a bunch of .myClass which means that the ajax request runs multiple times. How can I get it run only once when the user enters over the currentItem they are entering ?
currentItem.one("mouseenter", function () {
// rest of implementation
});
...and problem solved.
http://api.jquery.com/one/

jQuery.ajax() sequential calls

Hey. I need some help with jQuery Ajax calls. In javascript I have to generste ajax calls to the controller, which retrieves a value from the model. I am then checking the value that is returned and making further ajax calls if necessary, say if the value reaches a particular threshold I can stop the ajax calls.
This requires ajax calls that need to be processes one after the other. I tried using async:false, but it freezes up the browser and any jQuery changes i make at the frontend are not reflected. Is there any way around this??
Thanks in advance.
You should make the next ajax call after the first one has finished like this for example:
function getResult(value) {
$.ajax({
url: 'server/url',
data: { value: value },
success: function(data) {
getResult(data.newValue);
}
});
}
I used array of steps and callback function to continue executing where async started. Works perfect for me.
var tasks = [];
for(i=0;i<20;i++){
tasks.push(i); //can be replaced with list of steps, url and so on
}
var current = 0;
function doAjax(callback) {
//check to make sure there are more requests to make
if (current < tasks.length -1 ) {
var uploadURL ="http://localhost/someSequentialToDo";
//and
var myData = tasks[current];
current++;
//make the AJAX request with the given data
$.ajax({
type: 'GET',
url : uploadURL,
data: {index: current},
dataType : 'json',
success : function (serverResponse) {
doAjax(callback);
}
});
}
else
{
callback();
console.log("this is end");
}
}
function sth(){
var datum = Date();
doAjax( function(){
console.log(datum); //displays time when ajax started
console.log(Date()); //when ajax finished
});
}
console.log("start");
sth();
In the success callback function, just make another $.ajax request if necessary. (Setting async: false causes the browser to run the request as the same thread as everything else; that's why it freezes up.)
Use a callback function, there are two: success and error.
From the jQuery ajax page:
$.ajax({
url: "test.html",
context: document.body,
success: function(){
// Do processing, call function for next ajax
}
});
A (very) simplified example:
function doAjax() {
// get url and parameters
var myurl = /* somethingsomething */;
$.ajax({
url: myurl,
context: document.body,
success: function(data){
if(data < threshold) {
doAjax();
}
}
});
}
Try using $.when() (available since 1.5) you can have a single callback that triggers once all calls are made, its cleaner and much more elegant. It ends up looking something like this:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
// a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
alert( jqXHR.responseText )
});

Resources