Override asynchronous (XMLHttpRequest) activity?

R

Roadworrier

Hey, does anyone know how I can pause the processing of
XMLHttpRequests so that I can have the foreground interface respond to
user clicks?

I have 40 graphs drawing to the screen after getting 1000 points each
from a cgi contact with a remote server. (40 XMLHttpRequest calls, and
40,000 data points on which some statistics are calculated.)

If the user clicks on a button, it can take as long as 10 seconds for
the javascript that fires when the button is pushed to activate...
even if it's just creating an Alert()!

I want the XMLHttpRequests to load as quickly as possible UNLESS the
user does something, in which case I want to pause everything so the
user can feel like they're interacting well -- a button changes it's
css class to highlight a key letter or unhighlight it. (Of course it
works fine as is with Firefox and Opera, it's just the browser
everyone uses, Internet Explorer, that responds so sluggishly.)

- Stefan
 
J

Jorge

(Of course it
works fine as is with Firefox and Opera, it's just the browser
everyone uses, Internet Explorer, that responds so sluggishly.)

There's no cure for IE...
 
R

Roadworrier

Thanks for the reply Conrad.

I have no idea what you're doing in your scripts, but are you sure that
you're really sending *asynchronous* requests? Check if you have really
set the 'async' flag to true:

  (XHR object).open(method, uri, async);

Yes, I set the async parameter to true, and I can tell it's true
because I can watch the results return asynchronously from the server
with Firebug.
A locked-up user interface is usually the result of a synchronous
request - or, alternatively, bad application design:


Are you really sending *40* XHRs at the same time?
Why would you do such a thing?
And why would you be surprised by a lack of performance in this case?

Well, not exactly at the same time. On station with one trace is
showed on launch, one XHR. The user clicks to add a 2nd station, and
then a request for that new station is added. If the user clicks on a
different trace type then two more requests are sent, for a the 1st
station trace type 2, 2nd station trace type 2. If the user keeps
cheerfully clicking away, they'll eventually end up with up to 40
requests. Probably by the time they select everything a bunch of the
requests will be processed since it updates "realtime", but at least
half will still be remaining.

It wouldn't be a bad idea to rewrite my C cgi on the server end to be
able to handle more than one request at a time so that when there are
20 unprocessed requests they can be sent as a batch. It'll make the
feel a little less "realtime" but overall performance might be
perceived to improve.
As for your original question, no, you cannot "pause" XHRs. You can
cancel them (sort of), but if you design your application correctly, you
won't have to.

I was able to improve user feedback performance on IE by making it
slower; I set a 250ms setTimeout before processing any new XML
requests, and that allowed the user click highlight to get processed
much quicker. Still not as quick as I'd like, but maybe quick enough
to keep the scientists using this thing happy.

Any thoughts on redesign are welcome, if there are no solutions in
Javascript like "write this html (via JS) to screen at a higher
priority"...
 
T

Thomas 'PointedEars' Lahn

Roadworrier said:
Hey, does anyone know how I can pause the processing of XMLHttpRequests
so that I can have the foreground interface respond to user clicks?

I have 40 graphs drawing to the screen after getting 1000 points each ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
from a cgi contact with a remote server. (40 XMLHttpRequest calls, and ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40,000 data points on which some statistics are calculated.)

If the user clicks on a button, it can take as long as 10 seconds for the
javascript that fires when the button is pushed to activate... even if
it's just creating an Alert()!

ISTM you are asking the wrong question.

That the problem occurs only *after* the response messages were processed
would indicate that it is *not caused by XHR* (so the type of
request-response chain handling is irrelevant) but by the
single-threadedness of known ECMAScript implementations (the Specification
makes no statement to that end).

Therefore, the only thing that could help to work around the issue is moving
expensive parts of the algorithm into pseudo-threads created with the
host-defined methods window.setInterval() or window.setTimeout(). In
interoperable code, the timeout/interval length cannot be smaller than 10
ms; if there are several such operations to be performed and the previous
operation could delay the following one, self-calling window.setTimeout()
should be used instead of window.setInterval() in order to smooth operation
and to reduce CPU load (production code showed an average reduction by ca.
50% with equivalent code in Firefox 3.0.3/Gecko 1.9.0.3).

Example (quick hack):

x.onreadystatechange = function() {
if (x.readyState == 4 && /^[20]/.test(x.status))
{
var f = function() {
drawGraphs(x.responseText);
};

if (typeof window != "undefined"
&& /^(function|object|unknown)$/i.test(typeof window.setTimeout)
&& window.setTimeout)
{
window.setTimeout(f, 10);
}
else
{
f();
}
}
};


HTH

PointedEars
 
R

Roadworrier

ISTM you are asking the wrong question.

That the problem occurs only *after* the response messages were processed
would indicate that it is *not caused by XHR* (so the type of

This is true; the problem is the handling of the XHR returns, which
are building up in a way that's not very well controlled by me.
request-response chain handling is irrelevant) but by the
single-threadedness of known ECMAScript implementations (the Specification
makes no statement to that end).

Huh, I didn't know about that. Thanks.
Therefore, the only thing that could help to work around the issue is moving
expensive parts of the algorithm into pseudo-threads created with the
host-defined methods window.setInterval() or window.setTimeout().  In

That makes sense. I can have something check on how many requests are
currently being processed, and if it finds there's a big backlog, then
set the timeout. Otherwise go ahead without it. I have a few steps of
processing before the final graph appears, so I could put a wait in at
any point, if I deemed that particular thread wait-worthy.
interoperable code, the timeout/interval length cannot be smaller than 10
ms; if there are several such operations to be performed and the previous
operation could delay the following one, self-calling window.setTimeout()
should be used instead of window.setInterval() in order to smooth operation
and to reduce CPU load (production code showed an average reduction by ca..
50% with equivalent code in Firefox 3.0.3/Gecko 1.9.0.3).

Example (quick hack):

  x.onreadystatechange = function() {
    if (x.readyState == 4 && /^[20]/.test(x.status))
    {
      var f = function() {
        drawGraphs(x.responseText);
      };

      if (typeof window != "undefined"
          && /^(function|object|unknown)$/i.test(typeof window.setTimeout)

I understand this example with the exception of the above line.
          && window.setTimeout)
      {
        window.setTimeout(f, 10);
      }
      else
      {
        f();
      }
    }
  };

HTH

It helps thanks.

- Stefan
 
T

Thomas 'PointedEars' Lahn

Roadworrier said:
Thomas said:
[...]
if (typeof window != "undefined"
&& /^(function|object|unknown)$/i.test(typeof window.setTimeout)
&& window.setTimeout)

I understand this example with the exception of the above line.

It is an attempt at determining whether there is a `window.setTimeout'
property that can be called, so as to avoid runtime errors since this DOM
feature is not universally available. First it is tested whether there is a
`window' identifier, to prevent ReferenceErrors when accessing its
properties; then the result of the typeof operation on its `setTimeout'
property is being matched against with a regular expression for results that
indicate methods

Doing such feature tests is usually recommended, especially for host-defined
properties; however, this feature has a rather long history, so you may not
need to test for it (it remains to be seen whether it can be considered safe
to use anyway).

Search this newsgroup and the Web for isMethod() and isMethodType(), which
are wrapper methods for this kind of feature test.
It helps thanks.

You are welcome.


PointedEars
 
T

Thomas 'PointedEars' Lahn

[Full test expression restored]
Thomas said:
[...]
if (typeof window != "undefined"
&& /^(function|object|unknown)$/i.test(typeof window.setTimeout)
&& window.setTimeout)

I understand this example with the exception of the above line.

The statement is a feature test, an attempt at determining whether there is
a `window.setTimeout' property that can be called, so as to avoid runtime
errors since this DOM feature is not universally available.

First it is tested whether there is a usable `window' identifier, to prevent
ReferenceErrors when trying to access properties. If that test is
successful, the result of the `typeof' operation on its `setTimeout'
property is being matched against by a Regular Expression for operation
results that are known to indicate methods. If that test is successful, it
is tested whether the value of the property can be type-converted to boolean
true (since e.g. `typeof null === "object"' but `!!null === false'). The
last two tests are designed to prevent TypeErrors when the property is
called (as a method). Only if all tests have been passed, the following
block statement is executed.

Doing such feature tests is usually recommended, especially for host-defined
properties. However, this particular feature has a rather long history, so
you may not need to test for it (it remains to be seen whether it can be
considered safe to use anyway).

Search this newsgroup and the Web for isMethod() and isMethodType(), which
are wrapper methods for this kind of feature test.
It helps thanks.

You are welcome.


PointedEars
 

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

Forum statistics

Threads
473,780
Messages
2,569,607
Members
45,240
Latest member
pashute

Latest Threads

Top