Delay GET until all POST methods have completed, not just begun - ajax

I am experiencing two issues with my jQuery record-inserting process, and I am hoping that this wonderful SO community can help me to solve at least one of those issues. These are the issues:
Issue 1 - Intermittent server delay
The first issue relates to the fact that my Ubuntu 10.04 server seems to exhibit intermittent, 4.5 second delays when doing a POST of data to the mySQL database. Most POST commands are executed within a normal amount of milliseconds, but when a delay occurs, it always seems to be for approximately 4.5 seconds. This is not a busy, public server so it shouldn't be a matter of server load being the problem. These short videos demonstrate what I am trying to explain:
Video 1
Video 2
I have posted a question on serverfault and am awaiting some input from that forum which is probably more appropriate for this Issue 1.
Issue 2 - Timing of jQuery POST and GET Methods
The real issue that I am trying to resolve is to prevent the call to GET before all of the calls to POST have completed. Currently, I have implemented $.when.apply to delay the sending of GET. Here is the code for that:
function(){
$.when.apply(undefined, InsertTheAPPs()).done(function (){
$.ajax({
url: sURL + "fileappeal/send_apps_email",
success: function() {
var m = $.msg("my message",
{header:'my header', live:10000});
setTimeout(function(){
if(m)m.setBody('...my other message.');
},3000);
setTimeout(function(){
if(m)m.close(function(){
window.location.replace(sURL+'client/view');
});
},6000);
$('#ajaxShield').fadeOut(1000);
},
error: function(){
$.msg("error message",
{header:'error header', live:10000});
}
});
});
}
My problem arises due to the delay described above in Issue 1. The GET method is being called after all of the POST methods have begun, but I need the GET method to wait until all of the POST methods have ended. This is the issue that I need assistance with. Basically, what is happening is happening wrong here is that my confirmation email is being sent before all of the records have been completely inserted into the mySQL database.
Here is the code for the jQuery $.each loop. This is the code that needs to not only begin, but must end before the ajax call to fileappeal/send_apps_email above:
function InsertTheAPPs(){
$('input[name=c_maybe].c_box').each(function(){
var jqxhrs = [];
if($(this).prop('checked')){
var rn = $(this).prop('value');
jqxhrs.push(
$.ajax({
url: sURL + 'fileappeal/insert_app',
type:"POST",
dataType: 'text',
data: {'rn': rn},
error: function(data) {console.log('Error:'+rn+'_'+data);}
})
)
return jqxhrs;
}
});
}
Anyone have any suggestions for how I can workaround the server delay issue and prevent the call to the GET before all of the POST methods have completed? Thanks.

There's a small problem with your post. After you resolve it, this post should help you finish out your code: jQuery Deferred - waiting for multiple AJAX requests to finish
You're returning inside the .each but the function itself doesn't return anything. So your delay is not being given the array of ajax calls to wait for. And also, since your jqhrs is defined inside the each, the scope is per iteration over each c_box. Your method should look like this:
function InsertTheAPPs(){
var jqxhrs = [];
$('input[name=c_maybe].c_box').each(function(){
if($(this).prop('checked')){
var rn = $(this).prop('value');
jqxhrs.push(
$.ajax({
url: sURL + 'fileappeal/insert_app',
type:"POST",
dataType: 'text',
data: {'rn': rn},
error: function(data) {console.log('Error:'+rn+'_'+data);}
})
)
}
});
return jqxhrs;
}
You can also make your code easier. Since you just want to know if something is checked you can use the jquery pseudo class filter :checked such as:
function InsertTheAPPs(){
var jqxhrs = [];
$('input[name=c_maybe].c_box').filter(':checked').each(function(){
var rn = $(this).prop('value');
jqxhrs.push(
$.ajax({
url: sURL + 'fileappeal/insert_app',
type:"POST",
dataType: 'text',
data: {'rn': rn},
error: function(data) {console.log('Error:'+rn+'_'+data);}
})
)
});
return jqxhrs;
}
You could combine the filter on :checked into the main filter such as $('input[name=c_maybe].c_box:checked') but I left it in long form to really demonstrate what was going on.

Related

get data from ajax as an attribute value for callback function

Im new to ajax. I was trying to find the answer but was not lucky to find the corresponsing one. Basically I need to use an ajax to get some data and after that to put this data to the variable that later will be used as an attribute for the callback function with custom code.
This ajax part is just a method of myObject.
So, in the end I need this kind of functionality:
myObject.getData(url, callback(data) {
//my custom code of what I wanna do after ajax is complete
});
My code
/*
HERE COME SOME PROPERTIES AND OTHER METHODS WICH IS NOT THE CASE
*/
//This is where Im stuck
var getData = function getFromUrl($url) {
$.ajax({
type: 'get',
url: $url,
dataType: 'html',
success: function(html) {
$obj = html;//Im lost on this step!
},
});
};
P.S. Im trying to find an async way (without using async:false). Hope its possible
First I encountered many problems. My first problem was No Access-Control-Allow-Origin, most websites dont allow you to just scrap get their data for security reasons. Luckily someone already made a proxy: http://cors.io/ . Second problem is that you cant embed http on https, so I cant use jsfiddle to show you this working, it works on my local enviroment. After you get the raw html you have to parse it, you can do it with full regex, or you can power yourself with jquery like I'm doing on this example. What we're doing is checking stackoverflow.com and getting the amount of featured questions with .find(".bounty-indicator-tab").first().html(); But once you have the full html you can get any data you need.
var getData = function getFromUrl(url) {
$.ajax({
url: 'http://cors.io/?' + url,
crossDomain: true,
dataType: 'html',
success: function (html) {
var match = $(html).find(".bounty-indicator-tab").first().html();
console.log(match);
return match;
},
error: function(e) {
console.log('Error: '+e);
}
});
};
url = 'http://stackoverflow.com/';
data = getData(url);
//You cant use data yet because its working async

Ajax form submission

I am using ajax to submit a html input form and to redirect the output page when it is done. I tried two approaches but not sure why their results are different.
HTML form is something looks like this:
<form id="output_post" method="post" action="output.html">
<table class="input"></table>
</form>
Approach 1:
var frm = $('#output_post');
frm.submit()
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
success: function (url) {
window.location = "/output.html"
}
});
Approach 2:
var frm = $('#output_post');
$.ajax({
type: "POST",
url: frm.attr('action'),
success: function(url) {
window.location = "/output.html"
}
});
Approach 1 worked as I expected but I got error message in Approach 2 405 Method Not Allowed The method GET is not allowed for this resource. The difference between Approaches 1 and 2 is frm.submit(), and I am very sure both approaches have successfully initiate calculation.
Could anyone give me some hints on this issue? Thanks!
Firstly, I would actually say .submit() would be better reserved for allowing the Browser to actually go ahead with the natural/indented behaviour of following through to the action="" - if you wanted to actually have a different 'end result' - that's where $.submit() comes into help.
/**
* $.submit will listen to
* the .submit event, preventing
* default and allowing us to mimic
* the submission process and have our
* bespoke end result.
**/
$('#output_post').submit(function(event) {
event.preventDefault();
var getValues = $(this).serialize();
$.post( 'yourScript.php', getValues, function() {
window.location.href = "/output.html";
}
});
Comments to the Question
Approach One
This 'leaves' the function. Prematurely sending you away from the page before it's allowed to execute the rest of the script. The native .submit() will follow through to the action, which is the indented behaviour. Thus, $.ajax never ran.
Approach Two
Servers could/can decide on it's accepted content types.
No Data was sent to the URL, thus - defaulted to GET (Despite type: POST) But there's no serialised. array given.
This may 'act' different if you define 'data: values' in Approach Two.
Try this:
var frm = $('#output_post');
$('#output_post').submit(function(event) {
$.ajax({
type: "POST",
url: frm.attr('action'),
success: function(url) {
window.location = "/output.html"
}
});
});
-
Thanks

Chain multiple POST requests together using AJAX and jQuery

I received a suggestion from a prior question that I need to amend my code chain a series of POST requests together, but I don't have any idea how to accomplish this. Specifically, the advice I was given was to:
fire off a post, have its success handler fire off the next post,
etc... and then when all the posts are done, the final post's success
handler fires off the get
This strategy makes sense to me but I do not know how to implement. I am trying to prevent the call to GET before all of the calls to POST have completed. Currently, I have implemented $.when.apply to delay the sending of GET. Here is the code for that:
function(){
$.when.apply(undefined, InsertTheAPPs()).done(function () {
$.ajax({
url: sURL + "fileappeal/send_apps_email",
success: function() {
var m = $.msg("my message",
{header:'my header', live:10000});
setTimeout(function(){
if(m)m.setBody('...my other message.');
},3000);
setTimeout(function(){
if(m)m.close(function(){
window.location.replace(sURL+'client/view');
});
},6000);
$('#ajaxShield').fadeOut(1000);},
error: function(){
$.msg("error message",
{header:'error header', live:10000});
}
});
});
}
Here is the code for the jQuery $.each loop. This is the code that needs to not only begin, but must end before the ajax call to fileappeal/send_apps_email above:
function InsertTheAPPs(){
$('input[name=c_maybe].c_box').each(function(){
var jqxhrs = [];
if($(this).prop('checked')){
var rn = $(this).prop('value');
jqxhrs.push(
$.ajax({
url: sURL + 'fileappeal/insert_app',
type:"POST",
dataType: 'text',
data: {'rn': rn},
error: function(data) {console.log('Error:'+rn+'_'+data);}
})
)
return jqxhrs;
}
});
}
Could someone demonstrate how I can modify the code above to implement the strategy of chaining together the multiple POST calls?
Don't return from .each. It doesn't work that way. Instead do this:
var jqxhrs = [];
$(...).each(...
});
return jqxhrs;
Nothing is assigned to the return value of .each, which you can't get anyway. Returning from each allows it to be used like break/continue, which doesn't make sense in your context.
Moreover, the var jqxhrs inside of the each loop causes a new variable to be declared in that context on each iteration of the loop.

jQuery $.ajax failing silently, no error messages, and server responded with 200 OK

I am about to do my head in over this problem. I am using very simple jQuery ajax calls to get values from a database and populate a few select elements with the values, all returned as JSON. It works seamlessly for me on most browsers, however the client is reporting that neither them nor their clients are seeing the result.
I added some Console.log() commands along the way to make sure the code was executing, and it was. Sometimes the ajax GET to the URL in question works, other times is STILL returns 200 OK but the code simply does not execute further, and NO ajax error messages are shown in the error callback.
Here is the code I am using, can someone spot something obvious that may result in some browsers choking? If so, I'd be grateful if you could point it out:
var $j = jQuery.noConflict(true);
$j(document).ready(function(){
//console.log("jQuery has loaded");
//console.log("attempting to load country list via AJAX call now");
$j.ajax({
url: 'http://www.topplaces.co.za/templates/seb_one/positions/search_establishments_filter/search/db.php?q=countries&rand='+Math.random(),
success: function(data){
//console.log("Successfully got country list, going to populate the dropdown now");
if(data.length){
$j("#country").children("option:not(:first)").remove();
$j("#country").attr("disabled", false);
$j.each(data, function(resultIndex, result){
var o = new Option();
$j(o).html(result.country).val(result.country);
$j("#country").append(o);
})
//console.log("Country list should be populated now?");
}
},
error: function (xhr, ajaxOptions, thrownError){
//console.log(xhr.responseText);
console.log(thrownError);
},
dataType: 'json',
cache: false
})
$j("#country").live('change', function(){
var id = $j(this).val();
if(id == ""){
$j("#province").attr("disabled", "disabled");
$j("#town").attr("disabled", "disabled");
return false;
}
$j.ajax({
url: 'http://www.topplaces.co.za/templates/seb_one/positions/search_establishments_filter/search/db.php?q=provinces&c='+id+'&rand='+Math.random(),
success: function(data){
if(data.length){
$j("#province").children("option:not(:first)").remove();
$j("#province").attr("disabled", false);
$j.each(data, function(resultIndex, result){
var o = new Option();
$j(o).html(result.province).val(result.province);
$j("#province").append(o);
})
}
},
dataType: 'json',
cache: false
})
});
$j("#province").live('change', function(){
var id = $j(this).val();
if(id == ""){
$j("#town").attr("disabled", "disabled");
return false;
}
$j.ajax({
url: 'http://www.topplaces.co.za/templates/seb_one/positions/search_establishments_filter/search/db.php?q=towns&p='+id+'&rand='+Math.random(),
success: function(data){
if(data.length){
$j("#town").children("option:not(:first)").remove();
$j("#town").attr("disabled", false);
$j.each(data, function(resultIndex, result){
var o = new Option();
$j(o).html(result.town).val(result.town);
$j("#town").append(o);
})
}
},
dataType: 'json',
cache: false
})
});
})
I have commented out the Consol.log commands for the pure fact that the client was receiving error messages on IE as there is no console.
EDIT: I failed to mention that this a same domain request and therefore obeys the Same Origin Policy
The full site is here: http://www.topplaces.co.za/
On the right is a dynamic select group that starts with country and initiates AJAX calls until a Province is selected. The issue, a lot of people say that Country is no loading for them...
Kind regards,
Simon
Check if your server application always returns valid JSON object, otherwise it will not be accepted because you set dataType: 'json'. In this case, error function will be executed instead of success.
Remove dataType parameter and see what happens, try to parse incoming data with $.parseJSON() - it will throw an exception if you JSON is invalid.
I tried your site but no province is loading. The Json is empty. I tried accesing the php directly and it returns empty as well. Did you check your script?
URL Called
http://www.topplaces.co.za/templates/seb_one/positions/search_establishments_filter/search/db.php?q=provinces&c=Zambia&rand=0.12686952343210578&_=1335360594228
This are the params is see:
q:provinces
c:Zambia
rand:0.12686952343210578
_:1335360594228
Json Result:
[]
It's really random so I bet it's the php script not returning the json.
I also experienced this browser issue with json returned from an ajax call. The problem was that I had to look at different parts of the returned data in Firefox compared to IE. For Firefox, data.text was undefined so I had to use data.documentElement.firstChild to find the json:
var list = typeof data.text === 'undefined' ? jQuery.parseJSON(jQuery(data.documentElement.firstChild).text()) : jQuery.parseJSON(data.text);

how to send a variable to another page using ajax and mootools?

i am trying to send a variable to another page with a post request and i use this:
var x="hello";
var sender=new Request({
url:"page.html",
method:"post",
data:x
});
sender.send();
but how do i colected x after it gets sent to page.html? i tried reading everything i could find and work it out myself but i get strange results, so if anyone could give me a simple example i would appreciate it very much.
Here's a jsfiddle example (using the echo service to simulate a response)
http://www.jsfiddle.net/BVgNt/1/
var x = "bar";
new Request.HTML({
url: '/echo/html/',
data: {
x: "bar",
html: "x was '" + x + "'",
delay: 0
},
method: 'post',
onComplete: function() {
console.log(this.response.text);
document.id("target").set("html", this.response.text);
}
}).send();
the idea in the request class is that it fires an onComplete (onSuccess and onError too) events when done, with this.response containing various collections of responses, check that in the firebug console to see what you can extract or consult the mootools Request.HTML manual.

Resources