repeated XMLHttpRequest GETs and displaying result

R

RossGK

I'm a bit new to javascript - as will be obvious below.

I'm using an XMLHttpRequest to get a bit of data from server (django),
and it works nicely for single events. But my eventual outcome needs
to be a series of data transmissions. I figured requesting data over
and over until the data is some value that triggers the stop would be
an interesting first attempt. To move forward, I wrapped my initial
single data request in a for-loop to see if I could do multiple calls.

Here's my javascript stuff...

for (i=0;i<=5;i++) {
xmlHttp.onreadystatechange=function()

{ if (xmlHttp.readyState==4)
{ document.myForm.myvar.value=xmlHttp.responseText;
}
}
xmlHttp.open("GET","/ajax_data",true);
xmlHttp.send(null);

//alert("got here")
dopause(500); //wait 500ms
}

What I've noticed is that with that alert line commented out, nothing
seems to happen -ie I don't see the data receive. I expected to see
it flash 5 times (the server sends a random number)

When I put the alert in, the alert does in fact pop up, and the data
gets displayed.

Does the alert message cause a window refresh that I need to emulate
when the alert is not there. What do I need to do to make it cycle
through the get 5 times and actually show me what comes up, WITHOUT
using an alert pop!?

Thanks for any suggestions
 
A

after9

I'm a bit new to javascript - as will be obvious below.

I'm using an XMLHttpRequest to get a bit of data from server (django),
and it works nicely for single events.  But my eventual outcome needs
to be a series of data transmissions.  I figured requesting data over
and over until the data is some value that triggers the stop would be
an interesting first attempt.  To move forward, I wrapped my initial
single data request in a for-loop to see if I could do multiple calls.

Here's my javascript stuff...

        for (i=0;i<=5;i++) {
                xmlHttp.onreadystatechange=function()

                { if (xmlHttp.readyState==4)
                        { document.myForm.myvar.value=xmlHttp.responseText;
                        }
                }
                xmlHttp.open("GET","/ajax_data",true);
                xmlHttp.send(null);

                //alert("got here")
                dopause(500);        //wait 500ms
          }

What I've noticed is that with that alert line commented out, nothing
seems to happen -ie I don't see the data receive.  I expected to see
it flash 5 times (the server sends a random number)

When I put the alert in, the alert does in fact pop up, and the data
gets displayed.

Does the alert message cause a window refresh that I need to emulate
when the alert is not there.  What do I need to do to make it cycle
through the get 5 times and actually show me what comes up, WITHOUT
using an alert pop!?

Thanks for any suggestions

Wish I could test this, but I don't have the resources. I'm assuming
the myvar is a text field or text area in your form? Try appending
the responsetext to this section - not just setting it (not as a
permanent solution, mind you, but just to debug). It may be being
overwritten with a null response.
 
R

RossGK

Wish I could test this, but I don't have the resources. I'm assuming
the myvar is a text field or text area in your form?


Yes, the text gets assigned to myvar in the form below...

Response: <input type="text" name="myvar" />
</form>

.... and as I say works nicely in a single event, or with the alert
pop.
Try appending the responsetext to this section - not just setting it (not as a
permanent solution, mind you, but just to debug). It may be being
overwritten with a null response.

Not sure what you mean... do you mean like some sort of print
statement? (sorry my javascript weakness is showing)....
 
A

after9

Yes, the text gets assigned to myvar in the form below...

<form name="myForm">
        Stuff: <input type="text" onkeyup="getServerData();" name="username" /

        Response: <input type="text" name="myvar" />
</form>

... and as I say works nicely in a single event, or with the alert
pop.


Not sure what you mean... do you mean like some sort of print
statement?  (sorry my javascript weakness is showing)....

Try document.myForm.myvar.value+=xmlHttp.responseText;

instead of

document.myForm.myvar.value=xmlHttp.responseText;
 
R

RossGK

Try document.myForm.myvar.value+=xmlHttp.responseText;

instead of

document.myForm.myvar.value=xmlHttp.responseText;

Same behaviour results. When I keep the alert box in there, I see the
data get appended successively to the the previous data, and the form
field fills up. Without the alert box, nothing shows up.

Looking at my server log, interestingly I notice each time the alert
pops up, the data is displayed and I dismiss the alert, the server
shows that it has received a request and sent the data.

Without the alert box, the server shows only one request (and nothing
shows up on my page). So it seems the for-loop doesn't succeed in
making multiple requests without the alert box.

Will have to puzzle over that a bit longer...
 
T

Tom Cole

Same behaviour results. When I keep the alert box in there, I see the
data get appended successively to the the previous data, and the form
field fills up. Without the alert box, nothing shows up.

Looking at my server log, interestingly I notice each time the alert
pops up, the data is displayed and I dismiss the alert, the server
shows that it has received a request and sent the data.

Without the alert box, the server shows only one request (and nothing
shows up on my page). So it seems the for-loop doesn't succeed in
making multiple requests without the alert box.

Will have to puzzle over that a bit longer...

I can't see all your code, but it appears to me that without the pause
in there, you are reassigning the xmlhttprequest before it was
completed. You need to launch separate instances of xmlhttprequest,
rather than successively firing off the same one before it has
received a response. Know what I mean?
 
Á

Álvaro G. Vicario

RossGK escribió:
for (i=0;i<=5;i++) {
xmlHttp.onreadystatechange=function()

I'm not sure about your code (that's what frameworks have, you need to
be familiar with them) but it seems you only have one XMLHttp object and
you are overwriting its onreadystatechange handler on every loop
interation. I suppose only the last one works :-?

If you need to perform 6 simultaneous calls you need 6 separate
instances of your XMLHttp object type:

// Untested!
function YourXMLHttpObject(){
// ...
this.onreadystatechange = function(){
//...
}
}

var calls =[];
for(var i=0; i<6; i++){
var xml = new YourXMLHttpObject;
xml.foo = bar;
//...
calls.push(xml);
}
{ if (xmlHttp.readyState==4)
{ document.myForm.myvar.value=xmlHttp.responseText;
}
}
xmlHttp.open("GET","/ajax_data",true);
xmlHttp.send(null);

//alert("got here")
dopause(500); //wait 500ms

I don't know who dopause() works but, in general, I've found sleep()
clones of little help in JavaScript development (just an opinion).
 
H

Henry

RossGK escribió:


I'm not sure about your code (that's what frameworks have, you
need to be familiar with them)
?

but it seems you only have one XMLHttp object and
you are overwriting its onreadystatechange handler on
every loop interation. I suppose only the last one works :-?

If you need to perform 6 simultaneous calls you need 6
separate instances of your XMLHttp object type:
<snip>

But making 6 simultaneous calls is not what the OP wants; it is one of
the mistakes being made (and the HTTP limit on the number of
simultaneous connections to the server (which is 2) would make that
difficult to say the least (even if some browsers disregard that
limit)). 6 calls in sequence seems to be (nearer) what is wanted,
which implies the - onreadystatechange - handler arranging a
subsequent request, for which a single XML HTTP request object would
be sufficent.
 
R

RossGK

I can't see all your code, but it appears to me that without the pause
in there, you are reassigning the xmlhttprequest before it was
completed. You need to launch separate instances of xmlhttprequest,
rather than successively firing off the same one before it has
received a response. Know what I mean?

Understood, but that's why I had put in a little sleep function to
give the request a chance to come back before firing it off again.

The doPause is a simple loop...

function dopause(msecs)
{var date = new Date();
var nowDate= null;

do { nowDate= new Date(); }
while(nowDate-date < msecs);
}

So given that there IS a pause happenging between requests, it seems
like the alert box causes the equivalent of a screen 'repaint'...but
if that was the case I'd see the last one... and I don't. In fact,
the server side reports indicate only one request then a stall.

R.
 
R

RossGK

<snip>

But making 6 simultaneous calls is not what the OP wants; it is one of
the mistakes being made (and the HTTP limit on the number of
simultaneous connections to the server (which is 2) would make that
difficult to say the least (even if some browsers disregard that
limit)). 6 calls in sequence seems to be (nearer) what is wanted,
which implies the - onreadystatechange - handler arranging a
subsequent request, for which a single XML HTTP request object would
be sufficent.

Thanks for that followup. I would be worried about a proliferation of
calls, and sequencing issues. While if I use the same one, ensuring it
finishes before refiring (onreadystatechange) it seems safer, that I
won't have some network congestion returning request 3 after request 5
or something.

I guess the difference is that I'd like sequential calls rather than
simultaneous calls

?
 
T

Thomas 'PointedEars' Lahn

RossGK said:
Understood, but that's why I had put in a little sleep function to
give the request a chance to come back before firing it off again.

The doPause is a simple loop...

function dopause(msecs)
{var date = new Date();
var nowDate= null;

do { nowDate= new Date(); }
while(nowDate-date < msecs);

That is probably the worst thing you can do. Especially in a
single-threaded environment like this.

As it was said before, you need to start the next request in the
onreadystatechange event listener of the previous one. Quick hack:

// add feature tests and alternatives here
var xhr = new XMLHttpRequest();

// suppose you are within a block statement already;
// else use a function *declaration* instead
var f = function() {
if (xhr.readyState == 4)
{
if (!stopCriteria)
{
// wait for a while before the next request
// so we are not "hammering"; add feature tests here
var t = window.setTimeout(
function() {
window.clearTimeout(t);
t = null;
xhr.open("GET", "http://bar.example", true);
xhr.onreadystatechange = f;
xhr.send(...);
},
1000);
}
};

xhr.open("GET", "http://foo.example", true);
xhr.onreadystatechange = f;
xhr.send(...);

I think I have posted something similar here before.


PointedEars
 
H

Henry

Understood, but that's why I had put in a little sleep
function to give the request a chance to come back before
firing it off again.

Javascript is single threaded and running code will not be interrupted
in order to execute other code.
The doPause is a simple loop...

function dopause(msecs)
{var date = new Date();
var nowDate= null;

do { nowDate= new Date(); }
while(nowDate-date < msecs);
}

So given that there IS a pause happenging between requests,

No there is not. That function does not produce a 'pause' in any
useful sense of the word. The CPU (or one of its cores) will go to
100% for the duration of do-while loop (creating and destroying Date
objects and doing the comparisons as fast as it can) and no other
script execution will be allowed to interrupt that process. And the
loop that calls this function will behave the same; it will not be
interrupted and so no - onreadystatechange - handler will be executed
until the loop, and the code that triggers it, is finished.
it seems like the alert box causes the equivalent of a
screen 'repaint'...but if that was the case I'd see the
last one... and I don't.

Generally (and not by any specification) alters block javascript
execution and give the browser a chance to re-draw. The code
containing the alert will stop executing, and resume when the alert is
dismissed. However, whether an environment allows (possibly pending)
event or timer driven code to be executed while the alert is showing
is a feature of the environment; some do, most do not.
In fact, the server side
reports indicate only one request then a stall.

That is not unexpected. You should have parameterised the requests to
determine whether the request that arrived was the first or the last.
My money would be on its being the last.
 
R

RossGK

Thanks for the comments. Not sure I'm any closer to my goal, but there
are some things to explore in the postings and in my further JS ramp up...
 
J

Jorge

<html><head><script>
window.onload= function () {
var x= function (p) { return document.getElementById(p) },
xmlHttp= new XMLHttpRequest();
xmlHttp.i= 5;
xmlHttp.onreadystatechange= function () {
if (xmlHttp.readyState === 4) {
x('id').innerHTML= (xmlHttp.i--)+": "+xmlHttp.responseText;
setTimeout(xmlHttp.doItAgain, 500);
}
};
(xmlHttp.doItAgain= function () {
if (xmlHttp.i) {
xmlHttp.open("GET","/ajax_data",true);
xmlHttp.send(null);
} else {
xmlHttp= undefined;
}
})();
};
</script></head><body><span id="id"></span></body></html>

On a Mac, works fine in Safari, FF2, Opera 9.5, but not in FF3 : the
second call to xmlHttp.send(null) does nothing (!), Why ?.

HTH,
--Jorge.
 
D

Dr J R Stockton

In comp.lang.javascript message <988a822b-a124-462b-99e9-688ca1d62a22@m3
6g2000hse.googlegroups.com>, Thu, 26 Jun 2008 07:06:46, RossGK
The doPause is a simple loop...

function dopause(msecs)
{var date = new Date();
var nowDate= null;

do { nowDate= new Date(); }
while(nowDate-date < msecs);
}

That undesirable routine would be more efficiently written as

function dopause(msecs) { var done = +new Date() + msecs;
while (new Date() < done) {} }
 
R

Richard Cornford

Dr J R Stockton wrote:...
Thu, 26 Jun 2008 07:06:46, RossGK posted:

That undesirable routine would be more efficiently written as

function dopause(msecs) { var done = +new Date() + msecs;
while (new Date() < done) {} }

Is there any point in a CPU spinning its wheels more efficiently?

Richard.
 
J

Jorge

(...)
  // add feature tests and alternatives here
  var xhr = new XMLHttpRequest();

  // suppose you are within a block statement already;
  // else use a function *declaration* instead
  var f = function() {
    if (xhr.readyState == 4)
    {
      if (!stopCriteria)
      {
        // wait for a while before the next request
        // so we are not "hammering"; add feature tests here
        var t = window.setTimeout(
          function() {
            window.clearTimeout(t);
            t = null;
xhr.open("GET", "http://bar.example", true);
xhr.onreadystatechange = f;

Thomas, ISTM that that "window.clearTimeout(t)" is 100 % useless.
Setting "t= null" (?) is 200% useless too.
And there's no need to assign the handler "xhr.onreadystatechange = f"
more than once: that line could be deleted as well.

Regards,
--Jorge.
 
J

Jorge

in FF3 : the
second call to xmlHttp.send(null) does nothing (!), Why ?.

Hmmm, the onreadystatechange callback becomes === null after the first
httprequest.
So (in FF3) this runs fine :

<html><head><script>
window.onload= function () {
var xhr= new XMLHttpRequest();
xhr.e= document.getElementById('id');
xhr.i= 1e3;
(xhr.doItAgain= function () {
if (xhr.i) {
xhr.onreadystatechange= function () {
if (this.readyState === 4) {
this.e.innerHTML= (this.i--)+": "+this.responseText;
setTimeout(this.doItAgain, 0);
}
};
xhr.open("GET","/ajax_data",true);
xhr.send(null);
} else {
xhr= undefined;
}
})();
};
</script></head><body><span id="id"></span></body></html>

But this doesn't :

<html><head><script>
window.onload= function () {
var xhr= new XMLHttpRequest();
xhr.e= document.getElementById('id');
xhr.i= 1e3;
xhr.onreadystatechange= function () {
if (this.readyState === 4) {
this.e.innerHTML= (this.i--)+": "+this.responseText;
setTimeout(this.doItAgain, 0);
}
};
(xhr.doItAgain= function () {
if (xhr.i) {
xhr.open("GET","/ajax_data",true);
xhr.send(null);
} else {
xhr= undefined;
}
})();
};
</script></head><body><span id="id"></span></body></html>

I wonder why. Is it a bug or what ?
Both run fine in Safari, FF2 and Opera.

--Jorge.
 
T

Thomas 'PointedEars' Lahn

Jorge said:
Thomas, ISTM that that "window.clearTimeout(t)" is 100 % useless.

Once you've seen an error message popping up when navigating away or a UA
leaking memory because of a timeout or interval not properly cleared, you
will see how wrong you are here.
Setting "t= null" (?) is 200% useless too.

I will look into that later.
And there's no need to assign the handler "xhr.onreadystatechange = f"
more than once: that line could be deleted as well.

Obviously you don't know how XHR is implemented. An
nsIXMLHttpRequest::send() call clears all event listeners:

<http://www.xulplanet.com/references/xpcomref/ifaces/nsIXMLHttpRequest.html>


PointedEars
 
J

Jorge

Once you've seen an error message popping up when navigating away or a UA
leaking memory because of a timeout or interval not properly cleared, you
will see how wrong you are here.

I understand the need to clear a setInterval() timer, but not a
setTimeout() that has already timed out.
In which browser/browsers did you observe those leaks and/or error
messages ?
(IE, again ?)
I will look into that later.


Obviously you don't know how XHR is implemented.

Nope. I don't. But if you do, may you please explain why :
An nsIXMLHttpRequest::send() call clears all event listeners:

only in FF3... ?

Thanks,
--Jorge.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top