ajax success called before request has finished - javascript

at my whits end with this...
The problem I have is that around the same time (roughly 60-70 mins through the request) the success function is called for the ajax request, but the tomcat logs prove that the request is still running.
(perspective: the request is supposed to either return an empty string ("") or a html page (of errors) however when the success function is called, it returns a string of length 2 result = " " (2 white space characters)
I cannot get this to reproduce in chrome, only IE (which is a problem as we cater specificity for IE)
At first I though it was a jQuery issue as I have multiple polls running when the request is sent (to update jQuery progress bar info)
However...
When I test this with just one asynchronous ajax request (not jQuery) that calls a Java method that just loops for 3 hours printing out in the log each second, it always calls success around the 3600 second mark (still another 7200 seconds remaining).
Example code:
var http_request = false;
if (window.XMLHttpRequest) {
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/text');
}
}
else if (window.ActiveXObject) {
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!http_request) {
alert('Giving up: Cannot create an XMLHTTP instance');
return false;
}
url += "&random=" + Math.random();
http_request.open('GET', url, true);
http_request.onprogress = function () { };
http_request.ontimeout = function () { };
http_request.onerror = function () { };
http_request.onreadystatechange = function(){
if (http_request.readyState == 4) {
if (http_request.status == 200) {
result = http_request.responseText;
alert("success: ("+result.length+") ["+result+"]");
}
}
};
NOTE: this is not a time-out error (at least not an ajax one) as the ajax time-out options seem to work correctly and return time-out errors accordingly, but as I have said, its not a time-out error...the success function is called too early.
Hope somebody can help :)
Cheers,
Steve.
Update:
I've run the request with the network tab capturing and it shows that the result was aborted: here
Thanks #ArunPJohny, this has given me a new direction to look in. Is there some kind of "onAbort" ajax callback? As I would have thought this kind of response would be caught by the "error:" callback
Update 2:
I have since found my way to a number of SO topics, more notably: xmlhttprequest timeout / abort not working as expected?
Tim provides some useful links for catching the abort, but still no clue as to why its getting aborted.
follow-on: here

Related

XMLhttprequest returning empty responseText and readyState == 4 (WickedPF)

So we have this HTTP request call in our rails project which is working good, everything is fine. it calls the controller method and returns the value from that controller (in this case is going to be "true" or "false")
var httpRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.open('GET', url);
httpRequest.withCredentials = true;
httpRequest.responseType = 'text';
// httpRequest.setRequestHeader('Content-type', 'application/json');
httpRequest.onreadystatechange = function(){
$container.find('h4').html(JSON.stringify("Error"));
if (httpRequest.readyState === 4) {
$container.find('h4').html(JSON.stringify(httpRequest.response));
// $container.find('h4').html(JSON.stringify("SUCCESS"));
}
};
httpRequest.send();
Now, we want to export this to pdf, with the gem wicked-pdf. After struggling with this, since Wicked PDF converts the JavaScript to some local files and we had problems calling the controller method, because of the CORS, now we successfully call the controller method having a cookie. So, the method is called, but, responseText is empty when in normal conditions as I said at the beginning, it is not since it's building the HTML correctly.
So, the request is okay, is getting to the controller method, and is doing everything, but apparently this is not working:
render :json => #status, :layout => false
and I don't know why I've searched a lot about this and I'm kind of stuck. Why this is working in the normal project, but when trying to execute all this from local files, it doesn't, although is not giving any errors, the logs from rails are this:
INFO -- : Started GET "/monitor/devicestatus_alarms/30" for ::1 at 2020-01-24 09:22:18 +0000
INFO -- : Processing by MonitorController#devicestatus_alarms as JSON
INFO -- : Parameters: {"id"=>"30"}
INFO -- : Completed 200 OK in 45ms (Views: 0.2ms | ActiveRecord: 18.3ms)
I tried to increment the javascript-delay because maybe it required more time to do the calculations in the controller but nothing. responseText is still empty.
Also, we were checking for HTTP status == 200, but then we found out that with local files, when it succeeds, it always returns a status 4, which is returning, so apparently there are no errors. So, how can this request access the controller method, do everything and return with nothing?
Have you tried using AJAX calls to get this job done?
$.ajax({
url: "<your_url>",
type: 'GET',
dataType: 'text',
crossDomain: true,
xhrFields: {
withCredentials: true
}
}).then(function (data) {
< actions here >
}
}).always(function () {
< always action here>
});

Catch Facebook Access token on demand, but how?

I build a Firefox Extension and i'm using the graph api. At the moment i catch the access token of each user while starting the browser like:
https://stackoverflow.com/questions/10301146/facebook-login-within-a-firefox-add-on
This works fine but kind of stupid, because nobody will use the extension in each firefox session. So what i'm trying to do is, catch the access token or more accurately call the methode Wladimir Palant recommends on demand. My code looks like this, while getAccessToken() is the mentioned method.
onLoad: function (){
var NoteHandler = window.arguments[0];
var sjcl = NoteHandler.sjcl;
NoteHandler.getAccessToken();
decryptionDialog.noteHandler = NoteHandler;
decryptionDialog.sjcl = sjcl;
var currID = decryptionDialog.getID();
if(currID==""){
window.close();
return false;
}else{
http_request = new XMLHttpRequest();
http_request.open('Get', 'https://graph.facebook.com/'+currID+'/notes?access_token='+NoteHandler.token, false);
http_request.overrideMimeType("text/json");
http_request.send(null);
decryptionDialog.value = decryptionDialog.ResponseToArray(http_request.responseText);
....
But the problem is while getAccessToken() is still waiting for the access token, the onLoad()-Method won't wait and goes on. Therefore the NoteHandler.token is null while the request is send. Does anyone have an idea, because i'm relatively new to javascript.
You should rewrite this code to be asynchronous - it shouldn't assume that getAccessToken() will get the result immediately, there should be rather a callback parameter, a function to be called when the operation is done (can be a closure function). Something along these lines:
onLoad: function (){
var NoteHandler = window.arguments[0];
var sjcl = NoteHandler.sjcl;
NoteHandler.getAccessToken(function()
{
decryptionDialog.noteHandler = NoteHandler;
decryptionDialog.sjcl = sjcl;
...
http_request.open('Get', 'https://graph.facebook.com/'+currID+'/notes?access_token='+NoteHandler.token, false);
...
});
}
...
getAccessToken: function(callback) {
...
// All done - call the callback
callback();
}

Return Json Encode not set

I have a simple ajax request which gets a json encode array but it keeps telling me its not set... im thinking i have the return in the wrong place but am not sure where i put it... this is my function:
//Browser Support Code
function ajaxFunction(url,data){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
var response = ajaxRequest.responseText
}
}
queryString = "?dta="+data;
ajaxRequest.open("GET", url + queryString, true);
ajaxRequest.send(null);
return(response);
}
I then call the function like this:
var result = ajaxFunction('call.php','1');
alert(result);
The response is working as in console it says:
{"stage1":"550","stage2":"1500","stage3":"2000","total":"1"}
But I'm getting: response is not defined
Any ideas?
There are 2 resons why response is undefined:
syntax: it is defined in inner function, so it is not visible in outer scope. So your return (response) actually is return (window.response)
logical: the response is set in asynchronous callback, so when you synchronous function returns it would not be set even if you define it in the ajaxFunction itself.
To fix it have callback that will eventually return result. Check how jQuery.ajax return it result by calling success(data, textStatus, jqXHR) passed as argument to the function.
You can also force synchronous requests by passing "false" for third (isAsync) parameter of open call check MSDN or MDN.

Ajax response works after two clicks?

I just wrote a basic user-login system where the html page uses javascript to send the ajax request to a servlet which accesses through database.
Here's the js code
var res;
function getXMLObject()
{
var xmlHttp = false;
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP") // For Old Microsoft Browsers
}
catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP") // For Microsoft IE 6.0+
}
catch (e2) {
xmlHttp = false // No Browser accepts the XMLHTTP Object then false
}
}
if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest(); //For Mozilla, Opera Browsers
}
return xmlHttp; // Mandatory Statement returning the ajax object created
}
var xmlhttp = new getXMLObject(); //xmlhttp holds the ajax object
function handleServerResponse() {
if (xmlhttp.readyState == 4) {
res=xmlhttp.responseText;
}
else {
return false;
alert("Error during AJAX call. Please try again");
}
}
function ajaxFunction() {
var veid=document.getElementById("eid").value;
var vpwd=document.getElementById("pwd").value;
//window.alert('here inside ajaxFunction'+vconf+' '+vseid);
if(xmlhttp) {
xmlhttp.open("GET","check_login?eid="+ veid +"&pwd="+ vpwd,true); //this is the servlet name
xmlhttp.onreadystatechange = handleServerResponse;
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhttp.send(null);
}
}
function def()
{
//window.alert('hi');
ajaxFunction();
//alert('res:'+res);
if(res=='y')
{
return true;
}
else
{
document.getElementById("uhidden").style.color="#CC0000";
document.getElementById("uhidden").innerHTML="Invalid E-Mail ID or Password"
return false;
}
}
But the code works only after two clicks :(
Any help guys?
Your def function calls ajaxFunction and then straight away checks the res variable. However ajaxFunction just sends the AJAX request; it does not wait for the AJAX response to arrive. Your code is checking the res variable before it is being set from the AJAX response.
This is why it works on the second click - not because the res variable is being set by the second click's AJAX response, but because it is still set from the first click's AJAX response.
The solution is to re-arrange your code a bit. Move the code to display the invalid login message to where the AJAX response is received. In other words, replace the res=xmlhttp.responseText; line with some code to check if xmlhttp.responseText is not y and display the invalid login message.
I guess you call def()
Your Request ist asynchron(because you set the 3rd argument of open() to true ), but in def() you immediately after sending the request work with the the result:
ajaxFunction();
//alert('res:'+res);
if(res=='y')
At this time the request usually is not finished, the result not available yet
Put all code that has to work with the server-response into handleServerResponse()

Strange javascript behavior - multiple active XMLHttpRequests at once? Long running scripts?

I'm attempting to issue two concurrent AJAX requests.
The first call (/ajax_test1.php) takes a very long time to execute (5 seconds or so).
The second call (/ajax_test2.php) takes a very short time to execute.
The behavior I'm seeing is that I /ajax_test2.php returns and the handler gets called (updateTwo()) with the contents from /ajax_test2.php.
Then, 5 seconds later, /ajax_test1.php returns and the handler gets called (updateOne()) with the contents from /ajax_test2.php still!!!
Why is this happening?
Code is here: http://208.81.124.11/~consolibyte/tmp/ajax.html
This line:-
req = new XMLHttpRequest();
should be:-
var req = new XMLHttpRequest();
As AnthonyWJones stated, your javascript is declaring the second AJAX object which first overwrites the req variable (which is assumed global since there is no var) and you are also overwriting the ajax variable.
You should separate your code i.e:
function doOnChange()
{
var ajax1 = new AJAX('ajax_test1.php', 'one', updateOne);
var ajax2 = new AJAX('ajax_test2.php', 'two', updateTwo);
}
function AJAX(url, action, handler)
{
if (typeof XMLHttpRequest == "undefined")
{
XMLHttpRequest = function()
{
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
throw new Error( "This browser does not support XMLHttpRequest." )
};
}
url = url + '?action=' + action + '&rand=' + Math.random()
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4)
{
if (req.status == 200)
{
alert('' + handler.name + '("' + req.responseText + '") ')
handler(req.responseText)
}
}
}
req.open("GET", url, true);
req.send(null);
}
Regards
Gavin
Diodeus and Mike Robinson:
You guys didn't read my post fully. I know that one of the pages takes longer to execute than the other. That is the expected behavior of each page.
HOWEVER if you read my original post, the problem is that the callback for both pages ends up getting called with the HTML contents of the first page only.
AnthonyWJones and Gavin:
Thanks guys! That works like a charm! I guess I need to brush up on my Javascript!

Categories

Resources