Whenever I run this file the code runs up to the point where the send function fires and then it only fires if I have an alert function directly behind it, if I take out the alert("sent"); out then it replies with ServerReadyyState is:1.
What could possibly be the problem? Someone please help, I've tried it on my local machine and on my personal server and got the same results. Any help is greatly appreciated.
The Code:
/**
* #author d
*/
var xhr;
function getPlants(xhr) {
try {
xhr = new XMLHttpRequest();
} catch (microsoft) {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
xhr = false;
alert("ajax not supported");
}
}
}
xhr.open("GET", "db_interactions.php", true);
xhr.send(null);
alert("sent"); //the send function only works if this alert functions is here
if (xhr.readyState == 4) {
return xhr.responseText;
} else {
alert("Server ReadyState is:" + xhr.readyState);
xhr.abort();
//getPlants(xhr);
}
}
AJAX is asynchronus. You can't just check the ready state immediately after.
The correct design pattern is to assign a function for the AJAX call to run when the ready state changes.
xhr.onreadystatechange = function () { alert('It changed!') }
In that function, you'll want to check if the state is 4. If so, you're ready to process the output. If not, do nothing, since that function will be called a few times before the ready state is 4.
Requests take some amount of time. When adding an alert() the code is being stopped until the user clicks ok. So when you remove it the request is send and immedialty checked. Resulting in an unfinished request.
When you change your code to this:
xhr.onreadystatechange=state_change
xhr.send(null);
function state_change() {
if(xhr.readyState==4) {
return xhr.responseText;
} else {
alert("Server ReadyState is:"+xhr.readyState);
}
}
a certain function like in this case state_change gets called every time the state changes. So you can wait until the request is finished or until an errorcode comes up.
Related
I am updating text in text area with javascript every 2 seconds, however sometimes happen that entire page freezes and you have to close the tab (other tabs in browser are working normally, this happens to all people visiting the page).
This is how my code looks like:
function ajaxSyncRequest(reqURL) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", reqURL, false);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('server=" + server + "');
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200){
document.getElementById(\"1\").innerHTML = xmlhttp.responseText;
if (document.getElementById('check').checked) { document.getElementById(\"1\").scrollTop = document.getElementById(\"1\").scrollHeight; }
} else {
document.getElementById(\"1\").innerHTML = "Could not connect to remote server!";\n
}
}
}
And this is the 2 seconds timer:
function timer() {
ajaxSyncRequest("ConsoleGenerator");
window.setTimeout("timer()", 2000);
}
I am getting the text with POST method to Java Servlet. It works sometimes for hours and then it freezes and browser says "Page is not reposnding..." or sometimes it works just a few minutes and then it freezes...
Can anybody help please ?
(Assuming we fix the basic syntax errors in the code.) You're happily firing off a subsequent requests without waiting for previous ones to complete. If the ajax call ever takes more than two seconds, you'll have overlapping calls. That isn't a problem in and of itself unless your backend is serializing calls or similar, but it does set up a chaotic situation.
You're also making synchronous requests by specifying false as the third argument to the POST call. There's no need to make the request synchronous, and doing so (particularly every two seconds?!) will indeed tend to lock up the UI of the browser.
I would recommend waiting for the previous request to complete before scheduling the next one, and making the requests asynchronous so the browser UI isn't locked:
// Accept callback --------------v
function ajaxSyncRequest(reqURL, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", reqURL, true);
// async, not sync ----------^
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('server=" + server + "');
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
document.getElementById("1").innerHTML = xmlhttp.responseText;
if (document.getElementById('check').checked) {
document.getElementById("1").scrollTop = document.getElementById("1").scrollHeight;
}
} else {
document.getElementById("1").innerHTML = "Could not connect to remote server!\n";
}
callback(); // <== Call it
}
}
function timer() {
ajaxSyncRequest("ConsoleGenerator", function() { // Pass in a callback
setTimeout(timer, 2000);
});
}
That will wait for the ajax to complete and then schedule another update two seconds later. If you want to include the time the ajax call took in the two seconds instead, we can do some basic math:
function timer() {
var started = Date.now();
ajaxSyncRequest("ConsoleGenerator", function() { // Pass in a callback
setTimeout(timer, Max.max(0, 2000 - (Date.now() - started));
});
}
Side note: No need for the window. prefix on setTimeout (though it's harmless provided nothing's shadowed the global window), and rather than passing a string to it, just pass a function reference.
I have an asynchronous audio upload script that works perfectly but there is one issue that is bugging me. The only thing it messes up is the error handling as an error is handled with an xhr status of 0 but there is seemingly no error as the upload continues.
xhr.upload.addEventListener("progress", keepPage(file,xhr),false);
xhr.upload.addEventListener("progress", uploadProgress,false);
xhr.upload.addEventListener("load", uploadComplete, false);
xhr.upload.addEventListener("error", uploadFailed(xhr.status), false);
xhr.upload.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "http://" + document.domain + "/script.php", true);
xhr.send(fd);
var uploading = true;
uploaded = false;
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200) {
var response = xhr.responseText;
if (response == "success"){
var uploaded = true;
processSuccess();
}
else {
var obj = $.parseJSON(response); //parse error JSON array
errReport = obj.errReport
uploadFailed(errReport);
}
}
}
uploading_tools(file, xhr, uploaded);
The error event is fired as soon as the script starts uploading. I have put console.log(xhr.status) in the uploadFailed function and a status of 0 is fired.
I understand an xhr status of 0 is given when an ajax is called across domains but as you can see this is not the case.
If I cannot get rid of this annoying bug I will just have to ignore an xhr status of 0 in my error handling which is something I would like to avoid doing.
Edit:
xhr.open("POST", "http://" + document.domain + "/script.php", true);
xhr.upload.addEventListener("progress", keepPage(file,xhr),false);
xhr.upload.addEventListener("progress", uploadProgress,false);
xhr.upload.addEventListener("load", uploadComplete, false);
xhr.upload.addEventListener("error", uploadFailed(xhr.status), false);
xhr.upload.addEventListener("abort", uploadCanceled, false);
xhr.send(fd);
var uploading = true;
uploaded = false;
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200) {
var response = xhr.responseText;
if (response == "success"){
var uploaded = true;
processSuccess();
}
else {
var obj = $.parseJSON(response); //parse error JSON array
errReport = obj.errReport
uploadFailed(errReport);
}
}
}
uploading_tools(file, xhr, uploaded);
Always call open() before accessing any other property or calling any other method of XMLHttpRequest. Strange behaviour can occur otherwise.
EDIt
I just saw the light, you are not getting an error!
You have this line:
xhr.upload.addEventListener("error", uploadFailed(xhr.status), false);
You aren't assigning uploadFailed() as the event handler for the error event. You are calling uploadFailed(xhr.status), so you are assigning as the event handler the return value of the function! Of course, surely uploadFailed does not return anything, so in the end you don't have an error handler. But, of course, when this line is executed your function is called! And as the call to xhr.send() hasn't occured yet, xhr.status is 0.
You have to change the line to
xhr.upload.addEventListener("error", uploadFailed, false);
Just like you have the others:
xhr.upload.addEventListener("progress", uploadProgress,false);
xhr.upload.addEventListener("load", uploadComplete, false);
NEW EDIT
In response to your comment, it doesn't work because you're doing the same you were doing, and not what I told you to do. Let's see if I can explain it to you.
Suppose your uploadFailed function is like this:
function uploadFailed(error) {
console.log(error);
return true; //you won't have this line, but let's assume you do.
}
Now, you have this code:
xhr.upload.addEventListener('error', uploadFailed(errReport), false);
Well, what is this line doing? Exactly this:
var f = uploadFailed(errReport); //uploadFailed is being called, not assigned to f
xhr.upload.addEventListener('error', f, false); //f is not a function, but the value 'true'!
Do you get it? When that line is executed, you are calling your function and assigning the result, not assigning the function itself. If your problem is how to pass the error value to the error function, you can do it this way:
function uploadFailed() {
console.log(this); //when you assign this function as an event handler,
//'this' will be the object which fired the event (xhr.upload)
}
You don't need to pass the xhr object to the function, but if, for whichever reason you need to pass the error as an argument, then you've got to do this:
xhr.upload.addEventListener('error', function() { uploadFailed(xhr.status); }, false);
This way you are defining a new function that has your xhr object in its scope and can pass it to your error function.
I hope you get the difference between a function and a function call, because it is essential.
my task is to do a long running JS code. This routine generate a POST request, and when its over and need to, generates another according to the answer:
function routine (a)
{
var answer = createPostRequest (bla bla bla);
if (answer)
{
routine (a);
}
}
so it recursively calls itself as long as the answer is true. So far its good, but then browser freezes, or hangs too much. After a time, Firefox will tell me that script is running too long, and offers to stop it.
Instead of doing routine (a); I tried to do with a setTimeout with timing 1. The same things, but when I set 100 for timing, it looks ok. But there are unnecessarry waitings, plus its a subjective number (what if even that 100 causes problems?)
I need some kind of "message based" thing, like in Delphi/Windows programming: a program sends a message to itself. How can it be achived in JS?
Edit: the way I generating the request:
var ajax = createXmlHttp();
ajax.open ('POST', 'dsdsdsad.adsf', false);
var parameters = 'param=1';
ajax.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
ajax.setRequestHeader ("Content-length", parameters.length);
ajax.setRequestHeader ("Connection", "close");
ajax.send (parameters);
try
{
var answer = eval('(' + ajax.responseText + ')');
}
catch (error)
{
alert ('Error in the answer: '+ajax.responseText);
return;
}
I would assume your createPostRequest makes an AJAX call that can handle a callback.
If so, make sure the request is asynchronous and pass it a callback that tests the condition and makes the next call if needed.
function createPostRequest(address, callback) {
var ajax = createXmlHttp();
ajax.open ('POST', address, true); // make it async
var parameters = 'param=1';
ajax.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
ajax.setRequestHeader ("Content-length", parameters.length);
ajax.setRequestHeader ("Connection", "close");
// handle the async response
ajax.onreadystatechange = function() {
if (ajax.readystate == 4) {
try {
callback(eval('(' + ajax.responseText + ')'));
} catch {
callback(null);
}
}
};
ajax.send (parameters);
}
function routine (a) {
createPostRequest (bla bla bla, function(answer) {
if (answer) {
routine (a);
}
}
}
I am using jcaptcha for image verification in my form. Before the form is submitted I make an ajax call using javascript to validate the text entered by the user corresponding to the image displayed. I get the result and update the value of a textbox(imageVerification). After the function that makes this ajax call is executed I pick up the value from this just updated textbox(imageVerification) for the result.
Here is the problem: I am not able to pick up the value from this textbox(imageVerification).
it always shows up as blank.
Catch: if I use an alert() before picking up the value, I am able to pick up the value correctly. I ran this in firebug debug mode and found out that it works in debug mode even without using the alert.
It seemed there is a delay before which the value in the textbox(imageVerification) gets updated. So i introduced a setTimeout() method and was able to pick up the value.
But I dont feel this is the right solution. I am assuming javascript executes sequentially. So why is my statement which is picking up the value after it has been updated by a method not able to get it immediately. Result is even though the image verification is successfull, my check fails since it is not able to pick up the result value from the textbox.
Also, if I use a simple function to update the textbox(imageVerification) instead of a ajax call, I dont face this problem.
Here is the code I am using for the ajax call.
function fetchContainerContent(url, containerid) {
var imageValue = document.forms['ratingForm'].elements['jcaptcha'].value;
var req = false;
var parameterString;
if (window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
} else if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else {
return false;
}
req.onreadystatechange = function() {
requestContainerContent(req, containerid);
}
parameterString = "jcaptcha="+imageValue;
req.open('POST', url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.send(parameterString);
}
function requestContainerContent(req, containerid) {
if (req.readyState == 4 && (req.status==200 || window.location.href.indexOf("http")==-1)){
//document.getElementById(containerid).innerHTML = req.responseText
//document.getElementById(containerid).value=req.responseText;
document.forms['ratingForm'].elements[containerid].value = req.responseText;
}
}
This is the function for image verification:
function validateImage(){
if(isBlank(document.forms['ratingForm'].elements['jcaptcha'].value)){
showError('',"Please enter the text seen in the image above",'jcaptchaError');
return false;
}
fetchContainerContent('captchaController','imageVerification');
var obj = document.forms['ratingForm'].elements['imageVerification'];
//alert('val '+obj.value);
var vall = obj.value;
if(vall=='PASS'){
return true;
}
else{
showError('',"Image verification failed. Please refresh image and try again","jcaptchaError");
return false;
}
}
post my call to fetchContainerContent('captchaController','imageVerification'), the value for imageVerification textbox should be set. If I use the alert box which is commented after the fetchContainerContent('captchaController','imageVerification') call it works fine.
Please help me out. Thanks alot
UPDATED ANSWER: Misread program flow on first pass.
The basic problem is you're trying to get an immediate response from the validateImage() function (return true or false) when the XMLHttpRequest needs time to complete.
Move the actions taken based on the return to their own functions (validFunction, invalidFunction) and try this:
function validateImage() {}
if(isBlank(document.forms['ratingForm'].elements['jcaptcha'].value)){
showError('',"Please enter the text seen in the image above",'jcaptchaError');
return false;
}
var obj = document.forms['ratingForm'].elements['imageVerification'];
validReq = fetchContainerContent('captchaController','imageVerification');
validReq.onload = function () {
var validResp = this.reponseText;
if(validResp=='PASS'){
validFunction();
}
else{
showError('',"Image verification failed. Please refresh image and try again","jcaptchaError");
invalidFunction();
}
}
validReq.send(parameterString);
}
function fetchContainerContent(url, containerid) {
var imageValue = document.forms['ratingForm'].elements['jcaptcha'].value;
var req = false;
var parameterString;
if (window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
} else if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else {
return false;
}
parameterString = "jcaptcha="+imageValue;
req.open('POST', url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
return req;
}
I am using the following script to monitor whether I can connect to a web site in a regular interval (10 seconds in my sample code). I met with two issues, any ideas how to solve them?
If a web site is very slow and no response within 10 seconds (making PingWebSite not return), I find 2 second call to PingWebSite will be executed because of 10 second interval arrives. My purpose is I want only one call to PingWebSite is under execution, and if 10 seconds interval arrives and previous PingWebSite is executing, I want to prevent current PingWebSite from execution. Any ideas how to solve this?
I find a strange issue, when I connect to a very slow web site, and code path executes to "alert("connecting");", then I expect exception to be thrown for timeout, but in my debug, no exception is thrown. Any ideas how to catch timeout exception?
Here is my code,
var index = 0;
function setup() {
window.setInterval(PingWebSite, (10 * 1000));
}
function PingWebSite() {
var http_request = new XMLHttpRequest();
try {
http_request.open("GET", "http://www.google.com", true);
http_request.onreadystatechange = function() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
MonitorInformation.innerText = "http://www.google.com" + " Connection ok";
alert("ok");
}
else {
alert("fail");
}
http_request = null;
} // if if (http_request.readyState == 4)
else {
// if execute here, no exception will be thrown
alert("connecting");
}
} // end of function
http_request.send(null);
} // try
catch (e) {
alert("service is not available");
}
}
EDIT 1: I have followed advice here to modify my code. Here is the below version. The new issue is index value (e.g. 0) will be prompted in alert message box before ok/fail alert message box. I think index value (e.g. 0) should be prompted in alert message box after ok/fail alert message box. Any ideas why?
var index = 0;
var http_request;
var xhrTimeout;
var chkConn;
function setup() {
chkConn = window.setInterval(PingWebSite, (10 * 1000));
}
function WebMonitorTimeout() {
http_request.abort();
alert("timeout");
index = index + 1;
}
function PingWebSite() {
http_request = new XMLHttpRequest();
http_request.open("GET", "http://www.google.com", true);
http_request.onreadystatechange = function()
{
if (http_request.readyState == 4) {
if (chkConn) { clearInterval(chkConn); }
if (http_request.status == 200) {
alert("ok");
index = index + 1;
if (xhrTimeout) { clearTimeout(xhrTimeout); }
}
else {
alert("fail");
index = index + 1;
if (xhrTimeout) { clearTimeout(xhrTimeout); }
}
http_request = null;
} //if (http_request.readyState == 4)
} // end of event function
http_request.send(null);
xhrTimeout = setTimeout("WebMonitorTimeout();", 30000);
alert(index);
chkConn = window.setInterval(PingWebSite, (30 * 1000));
}
thanks in advance,
George
Duplicate of javascript connect to web site code not working
You can't do Cross Site XHR requests because of browser security
For your first problem, don't use setInterval – use setTimeout in the callback for your request:
http_request.onreadystatechange = function () {
if (http_request.readyState == 4) {
// ...
setTimeout(PingWebSite, 10000);
}
};
Don't forget to call your function once after it has been defined to start it off (after that setTimeout will be called every time after a request has finished.)
Note that in some cases you might not reach readyState 4. I haven't really looked into how other libraries handle those cases, but look at the source code of jQuery, for example, for inspiration.
<SCRIPT language=javascript>
// Needed for IE6 and older to replicate the standard XMLHttpRequest object
if (window.ActiveXObject && !window.XMLHttpRequest){window.XMLHttpRequest =
function(){progIds=new Array("Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0",
"Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP",
"Microsoft.XMLHTTP");for(i in progIds){try{return new
ActiveXObject(progIds[i]);}catch(ex){alert(progIds[i]);}}return null;};}
// Standard asynchonous AJAX code
var xhr = new XMLHttpRequest();
// You would normally trade out the location.href with an actual .ashx
// page. It's like this here only for testing, thereby requesting this
// same page back from the server.
xhr.open("POST",location.href,true);
// The function that will be called asynchronously when the server sends
// back its response
xhr.onreadystatechange=function(){
// If you're using the file system instead of a web server then xhr.status
// will come back as 0, not 200. And of course if the page isn't found
// then a web server will send back a status of 404. xhr.readyState is 4
// when the page is done.
if (xhr.readyState == 4 && xhr.status == 200) {
clearTimeout(xhrTimeout); // Looks like we didn't time out!
// Use xhr.responseText to parse the server's response
alert(xhr.responseText);
}
}
// Now that we're ready to handle the response, we can make the request
xhr.send("My excellent post info");
// Timeout to abort in 5 seconds
var xhrTimeout=setTimeout("ajaxTimeout();",5000);
function ajaxTimeout(){
xhr.abort();
alert("Well dang, the AJAX request timed out. Did you lose network "+
"connectivity for some reason?");
// Note that at this point you could try to send a notification to the
// server that things failed, using the same xhr object.
}
</SCRIPT>