Using the W3School example (https://www.w3schools.com/js/js_ajax_intro.asp):
<!DOCTYPE html>
<html>
<body>
<div id="demo">
<h1>The XMLHttpRequest Object</h1>
<button type="button" onclick="loadDoc()">Change Content</button>
</div>
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML =
this.responseText;
}
};
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
}
</script>
</body>
</html>
Can someone explain why the GET action occurs after the innerHTML is set?
Logically, I'm used to languages which progress from top to bottom, working on each line of code step by step.
When I read this for the first time, I assume that the innerHTML for the demo element will be blank, and that there's no action which re-sets the innerHTML to the results from ajax_info.txt following the server request. Thinking of this in back-end languages, had the innerHTML been a variable, it would have to be updated, and the last statement might appear like this:
document.getElementById("demo").innerHTML =
this.responseText;
Example in pseudocode using variables:
var x = '' or NULL;
var y = GET text from file on the server;
var x = y;
onreadystatechange is a listener, it is not executed straight away, but listens to the XHR request for that event.
When the event is triggered, for example when the response comes back from the server, then the code will be executed.
You can also exchange the order of xhttp.onreadystatechange and xhttp.open().
The request will only be sent to the server after excuting xhttp.send().
And in xhttp.onreadystatechange=function(){} you can find
if (this.readyState == 4 && this.status == 200){
// dom excution
}
which means dom excution after xhttp.send() sending the request to the server and the readyState==4 &&status==200.
In javascript there is no guarantee that every code will be execute one after another. If some line takes time , then the second line start excution. So here if some execution precedence is required then need to apply the callbacks.For the case of Ajax follow the synch or async way.
Related
I have locally recreated an embedded-script example from the W3Schools site, but it does not work properly. It executes, creating the expected HTML page, but the onclick-activated XHR function does not alter the innerHTML content as expected. Here is the original code from the relevant page (https://www.w3schools.com/xml/tryit.asp?filename=tryxml_httprequest):
<!DOCTYPE html>
<html>
<body>
<h2>Using the XMLHttpRequest Object</h2>
<div id="demo">
<button type="button" onclick="loadXMLDoc()">Change Content</button>
</div>
<script>
function loadXMLDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML =
this.responseText;
}
};
xhttp.open("GET", "xmlhttp_info.txt", true);
xhttp.send();
}
</script>
</body>
</html>
I've tried several things:
I created a local text file with the same name as the one being opened in the sample script, and put it in the same directory. Page loaded with button, nothing happened when it was clicked.
I added "tracers" to the script in the form of alerts to confirm the script's progression:
function loadXMLDoc() {
alert("main function successfully called");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
alert("onreadystatechange function successfully called");
alert("readyState: " + this.readyState + " " + "status: " + this.status);
if (this.readyState == 4 && this.status == 200) {
alert("readyState/status function successfully called");
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "xmlhttp_info.txt", true);
xhttp.send();
}
When executed, the first two alerts appeared as expected. The third appeared twice, reflecting a change in readyState from 1 to 4, but the status remained 0 in both alerts. The fourth "tracer" alert never appeared.
I altered the final conditional to allow for "status == 0", and the fourth alert appeared, and the button disappeared...replaced by nothing.
Just to be sure, I changed it so that the string "hello world" was directly added to the innerHTML, which worked.
I tried the same variants on a different workstation (both were running Ubuntu Linux btw, and I executed the code with both Firefox and Chromium).
Obviously, the responseText is coming up empty. And presumably this is because the request failed, as evidenced by the status remaining 0 instead of changing to 200.
It would be bad enough if I couldn't get this simple code to work, but here's the hair-tearing, teeth-gnashing part: I ran this same code sample a couple of days before, and it executed flawlessly. Furthermore, I had written a much more complicated script employing my new-found knowledge of xhr to load much larger files, store their contents in variables and perform .searchs on them, also without any problems. I was in the process of elaborating the code when it failed, and at first I thought I'd made a change that "broke" it. But as I rolled it back to more and more "primitive" versions - versions I knew had worked - I discovered xhr no longer worked at all, as corroborated by formerly executable tutorial code no longer working, either.
I don't remember if there was an interim update of Firefox or Chromium that might have affected things, but that seems like a pretty weak possibility.
What am I missing?
Thanks in advance,
Rob
I have made a simple XMLHttpRequest which does work, it sends request etc. Just like in W3 schools.
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demox").innerHTML = this.responseText;
}
};
xhttp.open("POST", "textx.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=" + textxx);
}
The problem starts when I try to trigger the request by clicking a link, which sends me to the php file which processes the request. I find it hard to understand on my current level why it doesn't work, since it worked with simple forms and such.
I get:
"Notice: Undefined index: fname ..."
So, I assume, it means the variable wasn't sent. Can someone explain? Or is there way to debug the things that are being sent from one page to another. All I found was a debugger in chrome which indeed captures the requests, but has no real use, since I get sent to the textx.php page and all is lost.
Not really sure, where your problem might be, maybe try:
var xhttp = new XMLHttpRequest();
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.open("POST", "textx.php", true);
xhttp.onreadystatechange = function() {
if (this.readyState === 4){
if(this.status===200 || this.status===0){
document.getElementById("demox").innerHTML = this.responseText;
}
};
var fname = "fname=" + textxx;
xhttp.send(fname);
}
You might console.log(xhttp); and see the step by step profile and find out where the problem might be.
Either way, I am still not sure, but I uploaded my page(code) to a hosting server and the code worked. PHP didn't show any warnings and all went as planned. The problem it seems has to do something with running a local server(WAMP). Changing PHP version didn't help. I may need to dig a little deeper on this.
i have been trying very unsuccessfully to download a binary file from my server using jquery-ajax, which i finally gave up. so now i am trying to use XMLHttpRequest instead. however, i cannot even get a simple example working.
strangely enough, this code does not appear to do anything. i copy/pasted this from w3schools and this example is near identical to many other examples. it does not work for me in either chrome or FF:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
// Action to be performed when the document is read;
}
};
xhttp.open("GET", '/blah/blah/output.png', true);
xhttp.send();
we go into the onreadystatechange function only once, on the open() statement with an xhttp.readyState equal to one, but not on the send() step. i should think it would at least throw some kind of error rather than do nothing at all.
also, as an experiment, i purposely fed the open() a bad url - but again no reply.
can anybody tell me what i might be doing wrong?
thank you very much.
Your code looks correct to me, which points to some external cause.
Is your code flowing all the way through to the end of the execution context? Browsers will hold onto network requests until the engine yields back to the browser.
For instance:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
// Action to be performed when the document is read;
}
};
xhttp.open("GET", '/blah/blah/output.png', true);
xhttp.send();
while(true){}
will never send the call.
First of all I'm sorry for the really vague title, but I have no clue how to name the title. So if someone has a better name, please let me know and I'll edit it.
I have made some sort of a calculator, where the cost of ownership gets calculated. The input of values comes from the user or a preset from a database. The presets can be chosen with a select, and I use the onchange-event to change input data.
<select id="myID" onchange="getPreset(this.value)">
<option>Some options...</option>
</select>
In the getPreset() function I do some stuff + I call another function which I use to get the data from a database via JSON.
function getInfo(name){
var xmlhttp;
if(window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest();
}
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
var info = JSON.parse(xmlhttp.responseText);
//process data
calculate();
}
}
xmlhttp.open("GET", "myphppage.php?name="+name, true);
xmlhttp.send();
}
This is how my code is now and it works fine and as it should. But before I had placed calculate(); after xmlhttp.send();, which didn't work as it should have. The data got calculated only AFTER I chose another option. For example: first time I chose option 1 - nothing happens. Second time I chose option 2 - data gets calculated like option 1 is chosen.
I get that it was just the wrong place to put the function, but here's what I found strange: if I put an alert before the calling of the function, the data did get calculated. So my code was as following (so you can see it visually):
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
var info = JSON.parse(xmlhttp.responseText);
//process data
}
}
xmlhttp.open("GET", "myphppage.php?name="+name, true);
xmlhttp.send();
alert("make it work.");
calculate();
}
As I have no idea why this is and I'm curious to know, I'm asking it here. I hope someone can help me explain.
It's because of everything is asynchronous. While the alert pops up you (eventually) get the data and it's calculated correctly. That's why it works. If the connection is veeeery slow or you click 'ok' on the alert button extremely fast, it might fail. That's why you should put it in the correct place :)
Been working on (what seemed like) a simple issues for a few days now and could use some help.
I call a php file on a button-click, do a bunch of server-side operations, and wish to change a few things in the HTML at the end of the php (change images, changing text, enabling buttons, etc.)
So, what I'm trying to do (for the test case here) is change an image twice. It works fine in the first set of code (script in the html file), but it doesn't work in the second set of code (script in the php file). I.e., I see oldImage when the page loads, secondImage when I click the button, but I never see newImage.
<button onclick="test()">Try The Test</button>
<img id="myImage" src="oldImage.jpg">
<script>
function test()
{
var img = document.getElementById('myImage');
img.src = 'secondImage.jpg';
xmlhttp=new XMLHttpRequest();
xmlhttp.open("testPhp.php",true);
xmlhttp.send();
}
</script>
Here's myPhp.php (all on one line in my code; two lines here, for readability):
$script = "<script> var img = document.getElementById('myImage');
img.src = 'newImage.jpg'; </script?";
echo $script;
Any ideas on why the script in myPhp.php doesn't work?
EDIT:
I changed the HTML portion to this, then changed myPhp.php to echo "Hello World", which shows up just fine within myDiv. However, I can't seem to echo the script. Is there any way to do this?
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","portTester.php",true);
xmlhttp.send();
If your ajax call returns markup, for it to have any effect, it has to be added to the DOM.
But I wouldn't recommend doing it this way. Instead, have your PHP file return the information (not a script), and then have the code receiving the information (in the onreadystatechange handler of the XHR object) read that information and take the relevant action.
For example, your PHP could simply return:
newImage.jpg
Then your ajax call would be:
function test()
{
var img = document.getElementById('myImage');
img.src = 'secondImage.jpg';
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange = handleReadyStateChange;
xmlhttp.open("testPhp.php",true);
xmlhttp.send();
function handleReadyStateChange() {
if (xmlhttp.readyState === 4 && xmlhttp.status >= 200 && xmlhttp.status < 400) {
// Request is complete and successful
img.src = xmlhttp.responseText;
}
}
}
If you need to send back richer information (as is frequently the case), look at using JSON.
You're not doing anything with the response to your AJAX call. In other words: You are calling the PHP script, the reply is printed, but is thrown away, because your Javascript isn't doing anything with it. You must add some code to interact with the reply. Here's a hint: Don't try to output Javascript from PHP, output something that you USE in your Javascript.
Add this to your Javascript after the xmlhttp.send() call:
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("myImage").src = xmlhttp.responseText;
}
}
And in your PHP script, put just this:
echo 'newImage.jpg';
One possible issue is that you are missing the semi-colon after your test() in the onclick. Also, your </script> tag is malformed; it reads </script? while it should read </script>. Also, where into the DOM is this echoing? It should go into the head of your document. Right now, it looked unspecified.