Ajax response works after two clicks? - javascript

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()

Related

run javascript from ajax

I use the following function to make an ajax call to a PHP that retrieves data from a MySQL database whenever an onChange-Event occurs. The result of the PHP is a JavaScript function including some data.
Basically, I copied all the code down to xmlhttp.send() from W3Schools.
Then, facing the problem of calling the JavaScript on my page, I added the part with $.getScript(...).
It works, but I have a feeling that calling getRun.php?run=... twice cannot be the best way.
function getRun(str) {
if (str == "") {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("txtHint").innerHTML = this.responseText;
}
};
xmlhttp.open("GET","getRun.php?run="+str,true);
xmlhttp.send();
$.getScript("getRun.php?run="+str, function() {
setTimeout();
});
}
}
Do you have any hints on what would be a better way?
To further explain my comment on your question:
Define the function you want to run from your Ajax result
Launch your Ajax request to your PHP backend.
The PHP backend returns a certain result, be it a string or some JSON, up to you.
Call the function in the Ajax success (or error, or complete even) callback.
E.g.
function getDataFromBackend(){
// Your Ajax request
// Seeing as you tried to use $.getScript, you might be using jQuery, so an example with jQuery
$.ajax({
method: 'POST',
url: 'yoururl.php',
data: {}, // You can put whatever data you wanna send in this object
success: runMeWithData // The success callback runs the function when the Ajax request comes back without errors.
});
}
function runMeWithData(dataFromAjax){
console.log(dataFromAjax); // Show the output of your backend in the Console
}

Second request receives the first one that was still processing

I have a request system where two unrelated functions are making requests to my server. But the problem is the response is not correct let me explain what is happening step by step:
A background function makes a request to the server
Server processes task 1
A second unrelated background function makes a request to the server
Client recieves response of task 1
The second function recieves that response that was for the first function.
The first function never gets a response.
Now i don't know how to solve it, but i know i need to distinguish them separately so theres no conflictions here.
This is my current code that handles the request stuff:
function call_back(result,func){
if(typeof(func) != 'undefined' || func != false){
func(result);
} else {
return false;
}
}
function caller(url,cfunc){
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function call_file(url,func){ //handles html files (not json_encoded)
caller(url,function(){
if ( xmlhttp.readyState== 4 && xmlhttp.status== 200 ){
call_back(xmlhttp.responseText,func);
}
});
}
function call_data(url,func,JsonBool){ //handles json_encoded data
caller(url,function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
call_back(JSON.parse(xmlhttp.responseText),func);
}
});
}
What can i do to my functions, for preventing this behaviour?
Here is an example of how you could structure your code - I have used this, it works, but it could be refined.
function Ajax(url, callback,args){
var xhttp = init();
xhttp.onreadystatechange = process;
function init() {
if(window.XMLHttpRequest)
return new XMLHttpRequest();
else if (window.ActiveXObject)
return new ActiveXObject("Microsoft.XMLHTTP");
}
function process() {
if (xhttp.readyState==4 && xhttp.status==200) {
if (callback) callback(xhttp.responseText,args);
else return xhttp.responseText;
}
}
this.Get=function(){
xhttp.open("GET", url, true);
xhttp.send(null);
}
}
To use it:
var url = '/someurl';
var ajax = new Ajax(url,yourCallback,parameters);
ajax.Get();
I believe DRobinson was talking about something like this but more robust. This should be a good example to get you started though.
It looks to me as though you're using a global/window variable for xmlhttp. If this is the case, certain parts of the second call will overwrite the first. Consider using an Object Oriented approach, or otherwise instantiating these as vars in different scopes.

How to do a request to the server and liberate JavaScript to continue processing

Is there a way to make a request and liberate JavaScript and HTML to do their own thing, leaving the Server to do its thing until it completes, at which point an event grabs control of JavaScript, dumps the data to a designated receiving end and ends the call?
I use this method for calling Python
function par_makeHttpObject() {
try {
return new XMLHttpRequest();
}
catch (error) {}
try {
return new ActiveXObject("Msxml2.XMLHTTP");
}
catch (error) {}
try {
return new ActiveXObject("Microsoft.XMLHTTP");
}
catch (error) {}
throw new Error("Could not create HTTP request object.");
}
And I call it as follows:
...
var request = par_makeHttpObject();
request.open("POST", "../getFdList?Fds=allFds", false);
request.send();
var dta = request.responseText.split("\n");
var cnt = 0;
for (var x in dta) {
try {eval(dta[x]);}
catch (error) {alert("JS Error - check JS part of syntax!\n" + dta[x]);}
}
...
The problem is that JavaScript sits and waits for a reply to the request and the user could be doing something else. Some calls take 5 minutes...
Any ideas would be appreciated.
DK
Use jQuery's ajax() function instead of rolling your own AJAX solution. ajax() defaults to asynchronous requests, so you can pass it a function that is called on request completion:
$.ajax({
type: "POST",
url: "../getFdList?Fds=allFds"
}).done(function( msg ) {
alert( "Response: " + msg );
});
That way, you can call ajax(), give it your callback function, and carry on with whatever other processing you need to do.
Another plus for jQuery is that it's pretty well cross-browser without any effort.
Yes, it's very easy in fact. Change the last parameter in your open call to "true":
(I pulled this from w3schools(Yes I'm aware of the sites bad rep, this is just an example))
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//THIS IS WHERE YOU GET THE SERVER RESPONSE
var response = xmlhttp.responseText;
}
}
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
}
The best part about AJAX is the ability to continue working on something else while the HTTP request is being made asynchronously.
$.post('../getFdList?Fds=allFds', {}, function(response) {
var dta = response.split("\n");
// ...
}, 'text');
// continue doing something else here
See also: $.post()

ajax success called before request has finished

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

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.

Categories

Resources