Javascript XMLHttpRequests in Loop? - javascript

I am trying to save an array of records into a mysql database but I always get the abort message in firebug except for the last save. How do I save the records using a loop for XMLHttpRequest? Here is my code:
function savingContent()
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
var rowindex = 0;
for (x in globalObj.AddedRows)
{
var rowData = "?q=" + globalObj.AddedRows[rowindex];
xmlhttp.open("POST", "insertRowData.php"+rowData, true);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-Length",rowData.length);
xmlhttp.send(null);
rowindex += 1;
}

There are quite a few problems with this code. Here are just the first ones I found:
The for (x in object) syntax should only be used when you want to iterate over all fields in an object. In this case you want to iterate over an array, so you should do it like this:
for (var rowindex = 0; rowindex < globalObj.AddedRows.length; rowindex++) {
}
When doing an HTTP POST, you shouldn't put the data you want to change into the URL. Put it in the body of the request - as the argument to xmlhttp.send(). You're actually explicitly passing a content length - that length is supposed to be the length of the data you pass to xmlhttp.send() - so by passing NULL this is almost certainly your main error.
Rather than using Firebug, it'd be better to use xmlhttp.onreadystatechange to figure out which of your requests are succeeding or failing. Don't assume that once you have it debugged the first time, it will always succeed from then on. Handle errors.

In addition to dmazzoni:
Every time your for loop sends an async xml request it overrides the previous request and therefore the previous one is aborted. You should create a new XMLHttpRequest (or ActiveXObject for IE) inside your for-loop or wait for the HTTP return call, before sending a new request.

Related

Explaining how document.getelementbyid.innerhtml prints text

Following other documentation, I have succesfully printed out a text file separated by line.
<!DOCTYPE html>
<html>
<head>
<script>
function readFile()
{
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)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText.split("\n");
}
}
xmlhttp.open("GET","OFCaddresses.txt",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv"><h2>"FILE.txt"</h2></div>
<button type="button" onclick="readFile()">FILE</button>
</body>
</html>
I am trying to better understand how this works if someone could explain. I understand how they define xmlhttp depending on the browser, but what does
document.getElementById("myDiv").innerHTML=xmlhttp.responseText.split("\n");
actually do? Does it change the content of myDiv from the text to the file content? What does onreadystatechange have to do with the button?
It appears you need to do a lot more reading on what javascript does and how it works.
xmlhttp.onreadystatechange=function() is assigning a function to the xmlhttp object that will get executed when the readystate changes. This means that as the xmlhttp object goes through it's various stages of requesting data, it will execute this function a number of times.
Within that function you have a check: if (xmlhttp.readyState==4 && xmlhttp.status==200)
This is saying if the readystate is 4 (complete - see here for more info on readystates) then continue to execute everything within the {} blocks.
Finally, you have this code
document.getElementById("myDiv").innerHTML=xmlhttp.responseText.split("\n");
This is using the document object which holds all the html on the page. The getElementById method searches the html objects for an item with the given id. You've got the following html
<div id="myDiv"><h2>"FILE.txt"</h2></div>
so document.getElementById("myDiv") finds this div. The innerHTML property returns the html of that div, which is currently your <h2> header.
xmlhttp.responseText.split("\n"); gets the response from your xmlhttp object and splits it into an array by new lines and sets this as the new value innerHTML object. When an array is printed in html, it is comma-separated.
Hope this gives you a better understanding. But these are pretty basic javascript commands so you have a lot of learning to go.
document.getElementById("myDiv")
access the element with ID myDiv.
document.getElementById("myDiv").innerHTML
access the innerHTML of element with ID myDiv
xmlhttp.responseText
get the body of the xmlhttp response (as opposed to the header or other information sent along with the response)
xmlhttp.responseText.split("/n")
split the response into an array, with the delimiter being the newline character.
document.getElementById("myDiv").innerHTML=xmlhttp.responseText.split("\n");
Replace everything that is inside the element with id myDiv with the response text, changing newlines into commas (since the array, when treated as a string, will use commas to separate array values).
Note: an AJAX request (which is what the whole xmlhttpRequest is all about) is asynchronous, that is, it will happen outside the normal course of the code you are running. So, you need a way to use the information once you get a response back. onreadystatechange is an event that will resolve when a response is received from the server (success or failure). which is why the function further tries to figure out readyState and status: to ensure the response was successful. If you have a slow internet connection or the server is far away you'll notice the asynchronous part more obviously than when it's all happening on your own computer: it may take a second or two to resolve.

how to abort a xmlhttprequest before starting a new request?

I got a cgi-script the performs a search according to the query-string it gets submitted.
That works all fine.
But since the search can take some time and the user might start another search. I want the first search to get aborted before a second search is started, but if I insert a xmlhttp.abort() at the beginning of my AJAXRequest function the cgi-script doesn't get started at all.
Can anyone tell me how this could be performed?
Thanks in advance!
and here is the AJAX-code snippet
var xmlhttp;
function AJAXRequest()
{
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)
{
window.document.getElementById("resultlist").innerHTML=xmlhttp.responseText;
}
}
var queryString= "from=03-01-2006&to=04-30-2006&pattern=345";
xmlhttp.open("POST","../cgi-bin/search.exe?"+queryString);
xmlhttp.send();
}
Yea, XMLHttpRequest.abort() is a correct method to use for AJAX request aborting.
In my opinion your problem is more kind of design problem and not technical.
Therefore my suggestion is to review the flow of how the user interacts with your application.
For example, the classical solution is to show the progress bar or spinner and disable the "Search" button while your request is not completed and revert this state on success or error.
I found my problem.
I tried to abort a request object that has just been created. The object has to be global. At least that's the only way I see how to achieve this.

Get a PHP variable with javascript?

I have a Javascript game running within a HTML5 canvas. Now I'd like to pass on a variable that is stored in an object in PHP to my program. What I'd like to have would be a function in my js like getVariable = function(){script that gets the variable from PHP and returns it as a string}
Any hints?
#Valentin - simply use javascript ajax call(Or jquery call if you like) to get the values from the php script. If your game has different values for different players you can start a session and persist the values across many calls to the script.For example -
Let say you want to get the health of the player from player.php which looks like
session_start();//start the session
if(!isset($_SESSION['health']))
$_SESSION['health'] = $var;//If there is no value for player health in the session
//initialize the default value
switch($_GET['x']){
case 'health' :
echo $_SESSION['health'];
break;
default :
echo $var;
break;
}
?>
and the corresponding pure javascript would be -
var health;
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)
{
health=xmlhttp.responseText;
}
}
xmlhttp.open("GET","player.php?x=health",true);
xmlhttp.send();
You could do the same in a much simpler fashion using the awesome jQuery -
var health;
var reqData=["x" : "health"];
var xhrObj = $.get("player.php",x)
.done(function( response ) {
health=response;//The echo text from server
})
.fail(function() {
alert('error');
});
You can learn more about jquery and ajax here -->
jQuery API
www.w3schools.com/ajax/‎ for the ajax tutorial
Javascript and the browser don't care what language you're using on your server to generate the HTML/JS, all they care about is what is generated in the end.
To do what you're thinking, you'd have 2 ways to do it:
Print the contents of the variable to the page when initially generating it.
Use an AJAX call to a script on your server that echo's the value, then parse it in JavaScript. If you do this, though, you'd have to use the session or a database, or another means of keeping state between pages.

Run entire PHP-file from Javascript with AJAX

on $(document).ready(function() in index.php, the below AJAX is executed, running the file getData.php:
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)
{
document.getElementById("dataSuccess").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","getData.php",true);
xmlhttp.send();
In the getData.php file, data is gathered from MySQL and put in JS-arrays:
var guestData = new Array("<? for ($j=0;$j< sizeof($guestData);$j++) { print ($guestData[$j]); ?>","<?php } $j = $j+1; ?>");
And finally, store the data in my js arrays into LocalStorage:
var guestDataCols = new Array();
guestDataCols = guestData[0].split(",")
var arrayIndex=0;
for(arrayIndex=0;arrayIndex<guestData.length-1;arrayIndex++)
{
localStorage.setItem(arrayIndex, guestData[arrayIndex]); // storing
}
EVERYTHING works! But the problem is that my AJAX code doesn't seem to run through the entire getData.php file since LocalStorage in yet empty after the php-file is executed via AJAX. However (and this is a big one), if I simply refresh getData.php in another window, data is stored perfectly and evernything works. I've also tried using jQuery for this as suggested in another Stack Overflow question
$('#dataSuccess').load('getData.php'); //instead for the AJAX code
but with the exact same and somewhat mediocre result. So my questions is, why isn't the AJAX script running the entire php file and HENCE, why is no data stored in LocalStorage?
JavaScript on an HTML page is not run when called by an XMLHttp request. The browser doesn't parse the pages that JavaScript receives over XMLHttp requests and therefore does not run the JavaScript. You would have to output to the browser for it to be run. Your best bet would be do have the PHP return the data you need and then extract it from the XMLHttp request. For example, the getData.php could return a JSON string containing the data you need. Then on the page with the XMLHttp request, you could parse that JSON string and save it to the localStorage on that page.
I think you're looking for jQuery.getScript

How can I get an ajax request to behave like a standard HTTP form submit

This is for the html representation on e restlet server, this is to enable forms to be committed with PUT and DELETE http verbs.
<script type="text/javascript">
function submitFormXMLHttpRequest(meth, url, formname){
var xmlhttp;
var params;
var form = document.getElementById(formname);
var fieldcount = form.elements.length;
if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
var form = document.getElementById(formname);
for (i=1; i<=(fieldcount-1); i++) {
if(form.elements[i].name != "") params = params + form.elements[i].name + "=" + form.elements[i].value + "&";
}
//alert(params);
xmlhttp.open(meth, url+"?"+params, true);
xmlhttp.send();
}
</script>`
`(Inserting HTML code example seems a problem, but here's the form)
form id="r1" action="resource1" method="PUT"
!--some ftl markup form input fields etc--
button onclick='submitFormXMLHttpRequest("PUT", "resource1" , "r1");' type="button"Submit/button
input type="submit" value="Submit" /`
When the button is pressed the PUT verb shows up in the server logs and is dealt with correctly. But the restlet would then ordinarily respond with the next representation of the results of the submit. This doesn't happen because it goes through as an ajax request. If I add Response.Redirect(url, true) it ends up submitting the form a second time as a GET.
The fact that your restlet handle your request as an Ajax request is probably because of the header set by XMLHttpRequest.
In order to avoid it, you could try to remove this header :
if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
xmlhttp.setRequestHeader("x-requested-with", null);
}
Because generally, it will be defined with "XMLHttpRequest", indicating it's an ajax request.
Edit: I know that with Play! Framework, you can force the method (PUT & DELETE) through the use of x-http-method-override= that can be very useful because those two actions are not common in a html page. Maybe you can find something similar in restlet?

Categories