Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #14040 > unrolled thread

XMLHttpRequest

Started by"Tom de Neef" <tdeneef@qolor.nl>
First post2012-05-19 12:50 +0200
Last post2012-05-21 12:42 -0700
Articles 8 — 3 participants

Back to article view | Back to comp.lang.javascript


Contents

  XMLHttpRequest "Tom de Neef" <tdeneef@qolor.nl> - 2012-05-19 12:50 +0200
    Re: XMLHttpRequest Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-05-20 23:29 +0200
      Re: XMLHttpRequest "Tom de Neef" <tdeneef@qolor.nl> - 2012-05-21 09:45 +0200
    Re: XMLHttpRequest Scott Sauyet <scott.sauyet@gmail.com> - 2012-05-21 06:26 -0700
      Re: XMLHttpRequest "Tom de Neef" <tdeneef@qolor.nl> - 2012-05-21 16:05 +0200
        Re: XMLHttpRequest Scott Sauyet <scott.sauyet@gmail.com> - 2012-05-21 09:01 -0700
        Re: XMLHttpRequest Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-05-21 18:31 +0200
          Re: XMLHttpRequest Scott Sauyet <scott.sauyet@gmail.com> - 2012-05-21 12:42 -0700

#14040 — XMLHttpRequest

From"Tom de Neef" <tdeneef@qolor.nl>
Date2012-05-19 12:50 +0200
SubjectXMLHttpRequest
Message-ID<4fb77ae9$0$6925$e4fe514c@news2.news.xs4all.nl>
With
  asyncRequestor = new XMLHttpRequest();
  asyncRequestor.onreadystatechange = processAsyncResponse;
I communicate with a server in async mode.
Event handlers will call this function with the appropriate arguments:

function informServer(callBackID,arguments) {
  asyncRequestor.open("POST","/"+callBackID+"?"+arguments,true);
  asyncRequestor.send(null)
}

and the response is handled by the callback function:

function processAsyncResponse() {
  var xml
  if ((asyncRequestor.readyState == 4) && asyncRequestor.responseXML)
    {
      xml = asyncRequestor.responseXML.firstChild;
      if (xml) analyzeXmlResponseDoc(xml.firstChild)
    }
}

This worked fine until I hit situations where several events are triggered 
in rapid succession, such as onchange in a <select> and onclick on the page.
What happens in that case? I found a reference where it says that an open() 
call will close requests still in progress but I can not find confirmation.
I imagine that the script is run in a single thread, so how are successive 
calls to informServer handled by processAsyncResponse()?
Tom

[toc] | [next] | [standalone]


#14045

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-05-20 23:29 +0200
Message-ID<1595659.oMNUckLgyt@PointedEars.de>
In reply to#14040
Tom de Neef wrote:

> With
>   asyncRequestor = new XMLHttpRequest();
>   asyncRequestor.onreadystatechange = processAsyncResponse;
> I communicate with a server in async mode.
> Event handlers will call this function with the appropriate arguments:
> 
> function informServer(callBackID,arguments) {
>   asyncRequestor.open("POST","/"+callBackID+"?"+arguments,true);

I am not sure it is such a clever idea to name a function parameter 
`arguments' when there is a built-in `arguments' object in the local 
execution context (ES 5.1, 10.6).

>   asyncRequestor.send(null)

Also, if a server accepts query parameters (only) in the URI of a POST 
request, and if a script allows to submit them verbatim, that is a potential 
security leak (URI length issues [0a] aside). [0b]

Usually, POST request parameters should go into the message body instead; as 
a result, a POST request's URI query part should almost always be empty, and 
its message body should *never* be empty (`null').  Therefore, a function 
allowing to submit a POST request should take an Array or Object of 
parameters, so that each parameter name and value can be checked, discarded 
or modified if invalid or potentially dangerous, and properly (URI-)escaped 
for the request.  (Of course, the same care has to be taken server-side; for 
example in server-side PHP, if you support POST requests, use $_POST, *not* 
$_REQUEST.)

> }
> 
> and the response is handled by the callback function:
> 
> function processAsyncResponse() {
>   var xml

You should append a semicolon here …

>   if ((asyncRequestor.readyState == 4) && asyncRequestor.responseXML)
>     {
>       xml = asyncRequestor.responseXML.firstChild;

… or declare and initialize the variable here.

>       if (xml) analyzeXmlResponseDoc(xml.firstChild)

Keep in mind that white-space text nodes – which may always occur in an XML 
document – are child nodes, too.  With XML documents, you would be well-
advised to access nodes directly, using XPath (evaluate()), 
getElementsByTagName(), and similar means.

>     }
> }
> 
> This worked fine until I hit situations where several events are triggered
> in rapid succession, such as onchange in a <select> and onclick on the
> page. What happens in that case? I found a reference where it says that an
> open() call will close requests still in progress but I can not find
> confirmation. I imagine that the script is run in a single thread,
> so how are successive calls to informServer handled by
> processAsyncResponse()?

Depends.  Implementations would likely vary, so you would do well not to get 
yourself into such a situation of race condition in the first place: Create 
and use a new object for each request; at the very least create and use a 
new object if there is a request in progress with the current one, i.e. the 
value of the `readyState' property is greater than 0 (uninitialized) and 
less than 4 (finished) [1].  jsx.net.http.Request() in JSX:http.js does just 
that [2]; however, optimizations are still possible.

Keep in mind that an HTTP client is supposed to limit the number of 
connections to the same server or proxy [3]; several HTTP clients in 
browsers do that [4]), so concurrent requests will very likely be queued.


PointedEars
___________
[0a] <http://stackoverflow.com/a/417184/855543>
[0b] 
<https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet>
[1] <http://msdn.microsoft.com/en-us/library/ie/ms534361(v=vs.85).aspx>
[2] 
<http://PointedEars.de/websvn/filedetails.php?repname=JSX&path=%2Ftrunk%2Fhttp.js&peg=242>
[3] <http://tools.ietf.org/html/rfc2616#section-8.1.4>
[4] 
<http://www.openajax.org/runtime/wiki/The_Two_HTTP_Connection_Limit_Issue>
-- 
When all you know is jQuery, every problem looks $(olvable).

[toc] | [prev] | [next] | [standalone]


#14049

From"Tom de Neef" <tdeneef@qolor.nl>
Date2012-05-21 09:45 +0200
Message-ID<4fb9f2a3$0$6868$e4fe514c@news2.news.xs4all.nl>
In reply to#14045
"Thomas 'PointedEars' Lahn" <PointedEars@web.de> schreef in bericht 
news:1595659.oMNUckLgyt@PointedEars.de...
> Tom de Neef wrote:
>>
>> function informServer(callBackID,arguments) {
>>   asyncRequestor.open("POST","/"+callBackID+"?"+arguments,true);
>
> I am not sure it is such a clever idea to name a function parameter
> `arguments' when there is a built-in `arguments' object in the local
> execution context (ES 5.1, 10.6).
>
Point taken...

>>   asyncRequestor.send(null)
>
> Also, if a server accepts query parameters (only) in the URI of a POST
> request, and if a script allows to submit them verbatim, that is a 
> potential
> security leak (URI length issues [0a] aside). [0b]
>
> Usually, POST request parameters should go into the message body instead; 
> as
> a result, a POST request's URI query part should almost always be empty, 
> and
> its message body should *never* be empty (`null').  Therefore, a function
> allowing to submit a POST request should take an Array or Object of
> parameters, so that each parameter name and value can be checked, 
> discarded
> or modified if invalid or potentially dangerous, and properly 
> (URI-)escaped
> for the request.  (Of course, the same care has to be taken server-side; 
> for
> example in server-side PHP, if you support POST requests, use $_POST, 
> *not*
> $_REQUEST.)
>
Although it worked fine as it was, I have taken your advice and moved the 
parameters into the message body. Works fine also but feels better.

>
>>       if (xml) analyzeXmlResponseDoc(xml.firstChild)
>
> Keep in mind that white-space text nodes - which may always occur in an 
> XML
> document - are child nodes, too.  With XML documents, you would be well-
> advised to access nodes directly, using XPath (evaluate()),
> getElementsByTagName(), and similar means.
>
XML is actually uncharted territory for me. (Your advice, some time ago, to 
use CDATA has been very useful.) If I ever start using XML in a more general 
way I will buy a book on it. As it is, I construct a <xml> string in the 
server in a very strict way. For the moment it will serve.

>> This worked fine until I hit situations where several events are 
>> triggered
>> in rapid succession, such as onchange in a <select> and onclick on the
>> page. What happens in that case? I found a reference where it says that 
>> an
>> open() call will close requests still in progress but I can not find
>> confirmation. I imagine that the script is run in a single thread,
>> so how are successive calls to informServer handled by
>> processAsyncResponse()?
>
> Depends.  Implementations would likely vary, so you would do well not to 
> get
> yourself into such a situation of race condition in the first place: 
> Create
> and use a new object for each request; at the very least create and use a
> new object if there is a request in progress with the current one, i.e. 
> the
> value of the `readyState' property is greater than 0 (uninitialized) and
> less than 4 (finished) [1].  jsx.net.http.Request() in JSX:http.js does 
> just
> that [2]; however, optimizations are still possible.
>
> Keep in mind that an HTTP client is supposed to limit the number of
> connections to the same server or proxy [3]; several HTTP clients in
> browsers do that [4]), so concurrent requests will very likely be queued.

If the number of concurrent HTTP connections is limited to two anyway, it 
makes more sense to queue requests from the start rather than to queue them 
only after two connections are in use.
I will experiment.
Thank you for your contribution.
Tom 

[toc] | [prev] | [next] | [standalone]


#14050

FromScott Sauyet <scott.sauyet@gmail.com>
Date2012-05-21 06:26 -0700
Message-ID<645cf917-7fb3-4a7b-9e36-8d03aa4ca965@x10g2000yqg.googlegroups.com>
In reply to#14040
Tom de Neef wrote:
>   asyncRequestor = new XMLHttpRequest();
>   asyncRequestor.onreadystatechange = processAsyncResponse;
>
> I communicate with a server in async mode.
> Event handlers will call this function with the appropriate arguments:
>
> function informServer(callBackID,arguments) {
>   asyncRequestor.open("POST","/"+callBackID+"?"+arguments,true);
>   asyncRequestor.send(null)
> }
> [ ... ]
> This worked fine until I hit situations where several events are triggered
> in rapid succession, such as onchange in a <select> and onclick on the page.
> What happens in that case?

The second call will override the first, and the first server response
will be ignored.

> I found a reference where it says that an open()
> call will close requests still in progress but I can not find confirmation.

Yes:

| Note: Calling this method an already active request (one for which
| open() or openRequest()has already been called) is the equivalent
of
| calling abort().
  -- Mozilla <https://developer.mozilla.org/en/XMLHttpRequest#open()>

and from the descriptio of the open() algorithm on a XMLHttpRequest
object:

| 15. Terminate the send() algorithm.
  - W3C <http://www.w3.org/TR/XMLHttpRequest/#the-open-method>


> I imagine that the script is run in a single thread, so how are successive
> calls to informServer handled by processAsyncResponse()?

Everything would proceed fine until a second open() call is made when
the first is processing.

If you want to use a fixed pool of XMLHttpRequest objects (or even
just one, as you are doing) then you really need to determine if the
object is in process before you call open() again.

I've never really bothered.  Just constructing new instances has not
caused me noticeable issues.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#14051

From"Tom de Neef" <tdeneef@qolor.nl>
Date2012-05-21 16:05 +0200
Message-ID<4fba4b92$0$6961$e4fe514c@news2.news.xs4all.nl>
In reply to#14050
"Scott Sauyet" <scott.sauyet@gmail.com> schreef in bericht 
news:645cf917-7fb3-4a7b-9e36-8d03aa4ca965@x10g2000yqg.googlegroups.com...
Tom de Neef wrote:
> asyncRequestor = new XMLHttpRequest();
> asyncRequestor.onreadystatechange = processAsyncResponse;
>
> I communicate with a server in async mode.
> Event handlers will call this function with the appropriate arguments:
>
> function informServer(callBackID,arguments) {
> asyncRequestor.open("POST","/"+callBackID+"?"+arguments,true);
> asyncRequestor.send(null)
> }
> [ ... ]
> This worked fine until I hit situations where several events are triggered
> in rapid succession, such as onchange in a <select> and onclick on the 
> page.
> What happens in that case?

The second call will override the first, and the first server response
will be ignored.

> I found a reference where it says that an open()
> call will close requests still in progress but I can not find 
> confirmation.

Yes:

| Note: Calling this method an already active request (one for which
| open() or openRequest()has already been called) is the equivalent
of
| calling abort().
  -- Mozilla <https://developer.mozilla.org/en/XMLHttpRequest#open()>

and from the descriptio of the open() algorithm on a XMLHttpRequest
object:

| 15. Terminate the send() algorithm.
  - W3C <http://www.w3.org/TR/XMLHttpRequest/#the-open-method>


> I imagine that the script is run in a single thread, so how are successive
> calls to informServer handled by processAsyncResponse()?

Everything would proceed fine until a second open() call is made when
the first is processing.

If you want to use a fixed pool of XMLHttpRequest objects (or even
just one, as you are doing) then you really need to determine if the
object is in process before you call open() again.

I've never really bothered.  Just constructing new instances has not
caused me noticeable issues.

Thank you.
Note PE's references: there is a limit (of two) to the number of 
XMLHttpRequest objects alive.
Tom

[toc] | [prev] | [next] | [standalone]


#14052

FromScott Sauyet <scott.sauyet@gmail.com>
Date2012-05-21 09:01 -0700
Message-ID<fd222c60-e269-42b6-b952-b45e32344cd2@j25g2000yqn.googlegroups.com>
In reply to#14051
Tom de Neef wrote:
> Note PE's references: there is a limit (of two) to the number of
> XMLHttpRequest objects alive.

That's two per server, and that limit is a bit out of date, as most
modern browsers, starting with IE8, upped the limit to 6.

You can see one list of these values per browser at the second column
of <http://www.browserscope.org/?category=network>.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#14054

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-05-21 18:31 +0200
Message-ID<2104344.5D107XkKLB@PointedEars.de>
In reply to#14051
Tom de Neef wrote:

> "Scott Sauyet" <scott.sauyet@gmail.com> schreef in bericht
> news:645cf917-7fb3-4a7b-9e36-8d03aa4ca965@x10g2000yqg.googlegroups.com...
> Tom de Neef wrote:
>> I found a reference where it says that an open()
>> call will close requests still in progress but I can not find
>> confirmation.
> 
> Yes:
> 
> | Note: Calling this method an already active request (one for which
> | open() or openRequest()has already been called) is the equivalent
> of
> | calling abort().
>   -- Mozilla <https://developer.mozilla.org/en/XMLHttpRequest#open()>
> 
> and from the descriptio of the open() algorithm on a XMLHttpRequest
> object:
> 
> | 15. Terminate the send() algorithm.
>   - W3C <http://www.w3.org/TR/XMLHttpRequest/#the-open-method>

So you have evidence that it might be so in one DOM implementation because 
of one Working Draft (or vice-versa).  That does not mean anything for the 
rest of XHR-supporting runtime environments.

>> I imagine that the script is run in a single thread, so how are
>> successive calls to informServer handled by processAsyncResponse()?
> 
> Everything would proceed fine until a second open() call is made when
> the first is processing.
> 
> If you want to use a fixed pool of XMLHttpRequest objects (or even
> just one, as you are doing) then you really need to determine if the
> object is in process before you call open() again.
> 
> I've never really bothered.  Just constructing new instances has not
> caused me noticeable issues.
^^
(sic!)

Of course, creating new objects when not needed will unnecessarily consume 
resources that could be more useful elsewhere.  And as garbage collection is 
not performed instantly (if at all), one should be wary to create new 
objects.

> Thank you.
> Note PE's references: there is a limit (of two) to the number of
> XMLHttpRequest objects alive.

No, you misunderstood.  I have only pointed out that the number of 
simultaneous connections from the same HTTP client to the same HTTP server 
or proxy is supposed to be limited.  XHR merely provides an interface to the 
runtime environment's HTTP client.  I think we can accept as an axiom here 
that the number of XHR objects that can exist in a program simultaneously is 
– just like that of other objects – only limited by the amount of available 
memory.


PointedEars
-- 
    realism:    HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness:    XHTML 1.1 as application/xhtml+xml
                                                    -- Bjoern Hoehrmann

[toc] | [prev] | [next] | [standalone]


#14064

FromScott Sauyet <scott.sauyet@gmail.com>
Date2012-05-21 12:42 -0700
Message-ID<2009e498-132d-4027-b1f2-9dd2827af10d@p16g2000yqc.googlegroups.com>
In reply to#14054
Thomas 'PointedEars' Lahn wrote:
> Tom de Neef wrote:
>> Scott Sauyet wrote:
>>> Tom de Neef wrote:
>>>> I found a reference where it says that an open()
>>>> call will close requests still in progress but I can not find
>>>> confirmation.
>
>>> Yes:
>
>>>| Note: Calling this method an already active request (one for which
>>>| open() or openRequest()has already been called) is the equivalent
>>>| of calling abort().
>>>   -- Mozilla <https://developer.mozilla.org/en/XMLHttpRequest#open()>
>
>>> and from the descriptio of the open() algorithm on a XMLHttpRequest
>>> object:
>
>>> | 15. Terminate the send() algorithm.
>>>   - W3C <http://www.w3.org/TR/XMLHttpRequest/#the-open-method>
>
> So you have evidence that it might be so in one DOM implementation because
> of one Working Draft (or vice-versa).  That does not mean anything for the
> rest of XHR-supporting runtime environments.

No, it doesn't necessarily mean anything for other environments, but
the latter document is also the one that Microsoft points to in its
page on XHR (<http://msdn.microsoft.com/library/ms535874.aspx>.)  I
don't have a support matrix for this feature.  Do you?  It might be
interesting to create one.


>>> [ ... ]
>>> If you want to use a fixed pool of XMLHttpRequest objects (or even
>>> just one, as you are doing) then you really need to determine if the
>>> object is in process before you call open() again.
>
>>> I've never really bothered.  Just constructing new instances has not
>>> caused me noticeable issues.
>
> ^^
> (sic!)

I'm not sure why that "sic" is necessary here, unless you think that I
don't know whether I've noticed such issues.

> Of course, creating new objects when not needed will unnecessarily consume
> resources that could be more useful elsewhere.  And as garbage collection is
> not performed instantly (if at all), one should be wary to create new
> objects.

While a case can be made for your suggestion, for my uses, I rarely
have the number of XHR calls in one page view that make me even
*consider* whether this would be an issue.

I've written object pooling code in many environments.  The overhead
is really only worthwhile when the cost of construction or destruction
of the objects is very high, or when rare resources can be used only
by explicitly configured objects.  I've tested creating XHR objects in
a number of browsers, and, while they are sometimes significantly more
costly to create than simpler objects, they have never crossed the
threshhold that makes me feel a need for a pool.  I've never tried
testing their destruction, but I've generally been quite content with
the automatic memory management of the garbage collectors in the
various implementation I've used.  (And yes, I went through the issues
of IE's cyclic reference counting problems!)  And as far as I can
tell, there is no issue of precious HTTP connections being owned by
one XHR object or another.  If there is, I'd love to see a reference
or a test case.

Do you use XHR objects?  Do you pool them for reuse?  If so, do you
have some related sample code you'd be willing to share?

  -- Scott

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web