I'm playing around a little bit with raw XmlHttpRequestObjects + Comet Long Polling. (Usually, I'd let GWT or another framework handle of this for me, but I want to learn more about it.)
I wrote the following code:
function longPoll() {
var xhr = createXHR(); // Creates an XmlHttpRequestObject
xhr.open('GET', 'LongPollServlet', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
...
}
if (xhr.status > 0) {
longPoll();
}
}
}
xhr.send(null);
}
...
<body onload="javascript:longPoll()">...
I wrapped the longPoll() call in an if statement that checks for status > 0, because I encountered, that when I leave the page (by browsing somewhere else, or by reloading it), one last unnecessary comet call is sent. [And on Firefox, it even causes severe problems when doing a page reload, for some reason I don't fully understand yet.]
Question: Is that status check the correct way to handle this problem, or is there a better solution?
My current answer - until proven false - is, that the solution is correct.
i like the simplicity of this loop.... i think the server side script has to sleep or atleast loop until it gets new data before its considered long polling though this is just normal polling. i would also add something to check if the reques fails though. wrapping that in a try catch bloch should do the trick
Related
I've been working with phonegap to build an app and have been using ajax to communicate with the server to get all the necessary data. Some of the pages take a few seconds to load (and I dont display the page until everything is loaded) and I would like a loading screen to appear while the client is communicating with the server and processing all the data.
I had everything working great until I decided to throw the the ajax calls into functions (I'm working with a few team members, so I thought it would be easier for them to use these ajax calls if they were in some nice functions). Now because of the ajax function is asynchronous, the loading screen turns on and off before the requests are finished processing. I would like my function to stop the execution of code (similar to an alert) so that the loading screen will turn off AFTER all the ajax calls are made.
Essentially I want my javascript code to look like this:
loading();
sendRequests();
notLoading();
where loading() displays the loading screen, and notLoading() turns the loading screen off. My sendRequests() function is specific to each page (each page has to send different requests depending on the functionality of the page)
if you guys are wondering what the loading() and notLoading() functions looks like, here you go
// functions to make loading screen appear and disappear
function loading() {
document.getElementById("blackout").style.display = 'block';
}
function notLoading() {
document.getElementById("blackout").style.display = 'none';
}
I looked into a few other posts about it
How to wait for ajax request to complete in javascript when synchronous option is not available?
http://www.hunlock.com/blogs/Snippets:_Synchronous_AJAX
Which those two links essentially tell you the same information, that the third parameter in request.open() needs to be set to false... well, I've tried that and it didn't work =/
here is an example of my getRequest() function so everyone can see what I'm trying to do:
// will send a GET request to the parameter url
function getRequest(url) {
var req = new XMLHttpRequest();
req.open('GET', url, false);
setHeaders(req);
req.onreadystatechange = function() {
if (req.readyState == 4) {
if( (req.status == 200) || (req.status == 0) ) {
if( (typeof req.responseText != "undefined") && (req.responseText != "") ) {
localStorage["request"] = req.responseText;
}
else {
alert("GR: Error talking to the server");
}
}
else {
alert("GR: Error talking to server");
}
}
}
req.send(null);
return parseJSON();
}
If anyone knows how I can fix this, I would be very appreciative!
I ended up just throwing the notLoading() function at all the exit statuses in the sendRequests() function. Kind of a pain, but seems to work now.
I'm using XHR 2 to upload/save files.
According to the response of the server I want to perform an action. For example if the responce is "Saved" I want to hide a div or if the response is "Not Saved" I want to show another div etc...
I implemented what appears to be a simple code that should be working , but is not
Here is the snippet of the XHR
//initialize
var xhr = new XMLHttpRequest();
xhr.open('POST', 'upload.php');
xhr.responseType="text";
xhr.onload = function() {
//if all ok....
if (xhr.status === 200)
{
//update html5 progress bar
progress.value = progress.innerHTML = 100;
//get the respnse
var data=xhr.response;
//convert it to sting - kind of overkill, I know, but I'm stack
var data2=data.toString();
//alert it -- works
alert('data2 '+data2);
//now, do something, according to the response -- NOT working, never alert anything
if (data2=="Not Saved"){alert('Ooops, not saved');}
if(data2=="Saved"){alert('It's all good');}
if(data2=="File too big"){alert('hey, you are watching Jake and Amir');}
document.getElementById('imagesaved').innerHTML=data;
}
//refers to if (xhr.status === 200)
else {document.getElementById("imagesaved").innerHTML="Connect to server failed";}
What is wrong here? This should be working right? Any suggestions?
Thanks
EDIT
I put the alerts for testing. What I actually want to do is call some functions.
If I put
if (data2=="Not Saved"){functionOne();}
if(data2=="Saved"){functionTwo();}
if(data2=="File too big"){functionThree();}
the functions never get called
if I put
if (data2!="Not Saved"){functionOne();}
if(data2!="Saved"){functionTwo();}
if(data2!="File too big"){functionThree();}
ALL the functions are called!!!
I still dont get it...Maybe its something with the response? Or the onload function?
Thanks again
What I finally did is make the server response with numbers, not text. So encoding does not matter any more...
This is the code
var xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status == 200)
{
var data=xhr.response;
if(data==1)
//say to the user is saved
{document.getElementById('imagesaved').innerHTML="Saved";}
//say to the user, there was an error
else{document.getElementById('imagesaved').innerHTML="Error";}
}
//say to the user that connection to the server failed
else {document.getElementById("imagesaved").innerHTML="Cannot connect";}
};
xhr.open('POST', 'upload.php');
xhr.send(formData);
This is a workaround. I dont know if its the right way to solve this problem , technically. I decided to post it anyway, to help others to quickly solve similar problems. If anyboy else has a better way to suggest , please do.
In this line : if(data2=="Saved"){alert('It's all good');}, you have to escape " ' ".
So convert it to : if(data2=="Saved"){alert('It\'s all good');}
Are you sure that the response of your ajax is text/plain ?
Look on the console (ctrl+shift+i on chrome, F12 on firefox), on net or network tab.
Look on console tab if you got some javascript errors too.
I am using the following Ajax function format:
var xmlhttp;
function addAddress(str)
{
if (window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
//specific selection text
document.getElementById('info').innerHTML = xmlhttp.responseText;
}
}
var addAddress = "add";
xmlhttp.open("POST", "sys.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var queryString = "&addAddress=" + addAddress;
xmlhttp.send(queryString);
}
function GetXmlHttpObject()
{
if (window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
if (windows.ActiveXObject)
{
return new ActiveXObject("Micorsoft.XMLHTTP");
}
return null;
}
Up until now, all of my Ajax functions, like the one above, have been running fine. However, now the function will work only sometimes. Now, sometimes I will have to click the onclick event a couple times to execute the function or the function will just hang, and then after about 4 minutes it will execute.
I tested parts of the function and found that the issue lies some where at the:
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
alert(xmlhttp.status);
//specific selection text
document.getElementById('info').innerHTML = xmlhttp.responseText;
}
When the function works, I can alert(xmlhttp.status) and get 200. However, when it's not working, the alert box doesn't even trigger. In fact, nothing happens, not even an error.
Could this be a server issue? I am kind of thinking my website got hacked, but I cannot find any issues accept that the Ajax functions are not executing properly.
Lastly, I do not get this problem on my localhost, it's only happening on the live website.
Any help will be greatly appreciated.
Thanks
First just confirm that the addAddress function is actually being called when you click the button or control that should trigger it.
Just a simple alert in the first line like this would work:
function addAddress(str)
{
alert('addAddress has been called!')
....
}
If you don't get the alert, make sure there isn't a javascript error on the page that is preventing the function from running. In firefox you press CTRL+SHIFT+J to see the error console for example.
If that part is working, trying putting the URL for the ajax request directly into your browser and diagnose it that way.
Looks like you are requesting this url with ajax:
sys.php&addAddress= (address goes here)
Check that the page will load directly in your browser. If not, the problem is not the ajax request, but something with the sys.php page itself - which you can then drill down on.
Hope that helps!
This wasn't the answer I was expecting, but I ended up having my web host (GoDaddy) change servers, and that resolved the problem. For almost a year, I was running IIS7 with PHP. Since I had never run into any problems, I just continued using that server. After the Ajax latency issue and not being able to figure out a solution, I figured I would just switch over to Apache. After the change, everything started running smoothly again.
I am thinking maybe there was a software update that I was not notified about. Or, maybe my website was getting hit with a DDoS, which was decreasing the performance of my Ajax requests. Lastly, maybe someone got into IIS and changed a setting. I don't know, all I know is that the minute the server was changed over to Apache was when the website started running normally again.
Thanks for everyone's suggestions.
Suppose I have
1)
a HTML document.
2)
This HTML document loads Javascript file "code.js" like this:
<script src="code.js">
3)
User clicks button which runs "fetchdata" function in "code.js",
4)
"fetchdata" function looks like this:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState==4) {
myjsdata = xmlhttp.responseText;
}
}
xmlhttp.open("GET", 'http://www.example.com/data.js', false);
xmlhttp.send(null);
...
Now how do I do the following successfully:
I want to insert/eval my Javascript in a way, so all functions in "code.js" including "fetchdata" and functions defined above/below can access the data (structures, declarations, pre-calculated data values etc.) in "data.js".
(If this was possible, it would be idea since I could wait loading the actual JS data file until the user explicitly requests it.)
jQuery always has something for everything:
http://api.jquery.com/jQuery.getScript/
Loads a javascript file from url and executes it in the global context.
edit: Oops, didn't see that you weren't using jQuery. Everyone is always using jQuery...
Just do:
var scrpt = document.createElement('script');
scrpt.src='http://www.example.com/data.js';
document.head.appendChild(scrpt);
i think you should take a look at this site
this site talks about dynamic loading and callbacks (with examples) - where you can call a function in the loaded script after it loads. no jQUery, just pure JS.
This depends on a lot of factors, but in most cases, you will want to load all of your code/html/css in one sitting. It takes fewer requests, and thus boast a higher perceived performance benefit. Unless your code file is over several Megabytes big, loading it when a user requests it is unnecessary.
In addition to all of this, modifying innerHTML and running scripts via eval can be very cumbersome and risky (respectively). Many online references will back this point. Don't assume that, just because a library is doing something like this, it is safe to perform.
That said, it is entirely possible to load external js files and execute them. One way is to stick all of the code into a newly created script tag. You can also just try running the code in an eval function call (though it isn't recommended).
address = "testscript.js";
var req = (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");
if(req == null) {
console.log("Error: XMLHttpRequest failed to initiate.");
}
req.onload = function() {
try {
eval(req.responseText);
} catch(e) {
console.log("There was an error in the script file.");
}
}
try {
req.open("GET", address, true);
req.send(null);
} catch(e) {
console.log("Error retrieving data httpReq. Some browsers only accept cross-domain request with HTTP.");
}
I'm trying to get a Firefox plugin to read data from a HTTP get, parse the results and present them as links in a bookmark-like drop-down menu.
My quesion then is: Does anyone have any sample code that will do this?
Having never developed one myself, I'm not certain how this is typically done in Firefox plugins, but since plugin scripting is JavaScript, I can probably help out with the loading part. Assuming a variable named url containing the URL you want to request:
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.onreadystatechange = function() {
if(this.readyState == 4) { // Done loading?
if(this.status == 200) { // Everything okay?
// read content from this.responseXML or this.responseText
} else { // Error occurred; handle it
alert("Error " + this.status + ":\n" + this.statusText);
}
}
};
xmlhttp.send(null);
A couple of notes on this code:
You may want more sophisticated status code handling. For example, 200 is not the only non-error status code. Details on status codes can be found here.
You probably want to have a timeout to handle the case where, for some reason, you don't get to readyState 4 in a reasonable amount of time.
You may want to do things when earlier readyStates are received. This page documents the readyState codes, along with other properties and methods on the XMLHttpRequest object which you may find useful.
Robert Walker did a great job of describing how to send the request. You can read more about Mozilla's xmlhttprequest here.
I would just add that the response would be found (using Robert's code) using
xmlhttp.responseText
(Edit - i didn't read closely enough, thanks Robert)
You didn't indicate exactly what the data was, although you mentioned wanting to parse links from the data. You could the xmlhttp.responseText as an xml document, parse out the links, and place it into a menulist or whatever you like.