serialized XMLHttpRequests

E

Eric S Johansson

I'm trying to figure out the right way to serialize a series of
XMLHttpRequest transactions. I'm starting out with a table and I
extract a set of elements from that table. Each set of elements is
packaged into a post request and delivered via XMLHttpRequest. I don't
want to run any request in parallel because each request may create up
to three or four seconds of high load on the server.

the problem I'm having is figuring out how to iterate over the list
given that the requests are handled asynchronously. What trigger do I
use to fire off the next request? The last technique I tried fires off
another send inside the onreadystatechange handler. Unfortunately, that
only sends off one message per submit button press.

so, what's the trick? Do I go to synchronous mode? do I need to create
a new XMLHttpRequest object every time and recursively walk the list of
requests? use a semaphore to detect the onreadystatechange handler
firing and then trigger off the next send requests?

looking forward to your advice,

---eric
 
V

VK

Eric said:
I'm trying to figure out the right way to serialize a series of
XMLHttpRequest transactions. I'm starting out with a table and I
extract a set of elements from that table. Each set of elements is
packaged into a post request and delivered via XMLHttpRequest. I don't
want to run any request in parallel because each request may create up
to three or four seconds of high load on the server.

"serialize" doesn't mean "have something as a series". "serialization"
(in simple words) is the process of converting an object into portable
form for server-client exchange or RMI. Some CS prof may get a heart
attack of such definition but close enough :)

the problem I'm having is figuring out how to iterate over the list
given that the requests are handled asynchronously. What trigger do I
use to fire off the next request? The last technique I tried fires off
another send inside the onreadystatechange handler. Unfortunately, that
only sends off one message per submit button press.

so, what's the trick? Do I go to synchronous mode? do I need to create
a new XMLHttpRequest object every time and recursively walk the list of
requests? use a semaphore to detect the onreadystatechange handler
firing and then trigger off the next send requests?

First of all you can make your XMLHttpRequest synchronous:
myObject.async = false;

That will freeze the page for each call - that may be OK if you want
prevent users of doing nasty/stupid things before next response is
received. Or it may be not acceptable.

Or you can monitor readyState over onreadystatechange and launch the
next request as soon as the previous is done.

Neither of both require multiple objects - you can use the same one for
all requests.

<http://www.ajaxtoolbox.com> may be interesting to you.
 
T

Thomas 'PointedEars' Lahn

Eric said:
I'm trying to figure out the right way to serialize a series of
XMLHttpRequest transactions. I'm starting out with a table and I
extract a set of elements from that table. Each set of elements is
packaged into a post request and delivered via XMLHttpRequest. I don't
want to run any request in parallel because each request may create up
to three or four seconds of high load on the server.

the problem I'm having is figuring out how to iterate over the list
given that the requests are handled asynchronously.  What trigger do I
use to fire off the next request?  The last technique I tried fires off
another send inside the onreadystatechange handler.  Unfortunately, that
only sends off one message per submit button press.

Then your object model is flawed or does not fit the approach.
so, what's the trick?  Do I go to synchronous mode?  

It is a possibility that reduces responsiveness of the client but not
necessarily one that also reduces server load.
do I need to create a new XMLHttpRequest object every time

No, it is enough if you change the request parameters, e.g. if the target
resource changes, call the open() method of the XMLHttpRequest object with
the different resource URI again and, after that, assign the event
listener(s) again.
and recursively walk the list of requests?

I do not understand what recursion has to do with this.
use a semaphore to detect the onreadystatechange handler
firing and then trigger off the next send requests?

It is the `readystatechange' event that is firing and the "semaphore"
(IMHO "flag" is the better word) for that is the `onreadystatechange'
event handler calling the assigned event listener, so no. Just assign
a different event listener when needed.

Although I do not understand why more than one request is necessary
here, the following asynchronous approach works in Firefox 1.5/Linux:

var x = new XMLHttpRequest();
x.open("POST", "foo");

// set request headers if supported

x.onreadystatechange = function()
{
if (x.readyState == 4 && x.status == 200)
{
// may not be necessary
x.open("POST", "bar");

x.onreadystatechange = function()
{
if (x.readyState == 4 && x.status == 200)
{
// may not be necessary
x.open("POST", "baz");

x.onreadystatechange = function()
{
if (x.readyState == 4 && x.status == 200)
{
// done
}
};

x.send("data3");
}
};

x.send("data2");
}
};

x.send("data");

(As long as you use different event listeners, you can of course encapsulate
each subprocess in a user-defined object. You can implement this object so
that an existing XMLHttpRequest object can be reused.)

Or you make synchronous requests, blocking the client until a response is
received:

var x = new XMLHttpRequest();
x.open("POST", "foo", false);

// set request headers if supported

x.send("data");

if (x.status == 200)
{
// may not be necessary
x.open("POST", "bar", false);

x.send("data2");

if (x.status == 200)
{
// may not be necessary
x.open("POST", "baz", false);

x.send("data3");
if (x.status == 200)
{
// done
}
}
}


HTH

PointedEars
 
T

Tony

VK said:
Eric S Johansson wrote:
"serialize" doesn't mean "have something as a series". "serialization"
(in simple words) is the process of converting an object into portable
form for server-client exchange or RMI. Some CS prof may get a heart
attack of such definition but close enough :)

serialize: v : arrange serially;

serial: adj:

(Computer Science)
1. Of or relating to the sequential transmission of all the bits of
a byte over one wire: a serial port; a serial printer.
2. Of or relating to the sequential performance of multiple
operations: serial processing.

:)
 
E

Eric S Johansson

VK said:
"serialize" doesn't mean "have something as a series". "serialization"
(in simple words) is the process of converting an object into portable
form for server-client exchange or RMI. Some CS prof may get a heart
attack of such definition but close enough :)

you're right. I was using the term wrong. I was thinking in terms of
opposite of parallel. Sequential would've been a better term. My
apologies for word abuse.
First of all you can make your XMLHttpRequest synchronous:
myObject.async = false;

That will freeze the page for each call - that may be OK if you want
prevent users of doing nasty/stupid things before next response is
received. Or it may be not acceptable.

not terribly wonderful but maybe what I need to do.
Or you can monitor readyState over onreadystatechange and launch the
next request as soon as the previous is done.

I've tried this and I've enclosed a test function I was using for
experimenting with this technique and learning JavaScript at the same
time. I'm sure you'll be able to give me grief over lots of things.

if you look in the body of anonymous function assigned to
onreadystatechange, the purpose of this anonymous function is twofold.
First is to change visible elements in the browser window in the second
is iterating over a list of data I'm sending to a server one element
that time I'm doing this because it's a natural place to implement the
user interface change and then move to the next data element that I'm
operating on. In my naïve conception of the XMLHttpRequest environment,
I thought that another send would reset onreadystatechange and let me
wait again. obviously, it doesn't. It doesn't even let me send a
second request.

I'll probably go with synchronous request just because it's easier. I
do wish someone would update documentation on this topic because so far
everything I've seen has said go async.

the really annoying thing (for me) is that what I want to do really
isn't that difficult conceptually. You have a list of data, you want to
send that data to the server one element at a time. Why should it be so
hard especially if you're trying to follow generally recognized
practices for the toolset.

Neither of both require multiple objects - you can use the same one for
all requests.

that has yet to be proven :) I'll let you know what blows up in my
face again.
<http://www.ajaxtoolbox.com> may be interesting to you.

it does look interesting and if I ever have to do something like this
again, I'll probably go that route. in the meantime, this is only
supposed to be a two-day project and let's just say it's over budget.

var table_list = null;
var table_index = 0;

function processtab(){
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
alert("got XMLHttpRequest");
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
build_table();

self.xmlHttpReq.open('POST', "/cgi/test", true);
self.xmlHttpReq.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');

self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {

if (table_index < table_list.length){

var el = table_list[table_index];
var working = el;

while (working.tagName != "TR"){
working = working.parentNode;
}

working.style.visibility = 'hidden';
working.style.display = 'none';
table_index += 1;
self.xmlHttpReq.send(send_query_string());
}
}
} ;
self.xmlHttpReq.send(send_query_string());
return false;
}
 
V

VK

Eric said:
in the meantime, this is only
supposed to be a two-day project and let's just say it's over budget.

var table_list = null;
var table_index = 0;

function processtab(){
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
alert("got XMLHttpRequest");
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
build_table();

self.xmlHttpReq.open('POST', "/cgi/test", true);
self.xmlHttpReq.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');

self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {

if (table_index < table_list.length){

var el = table_list[table_index];
var working = el;

while (working.tagName != "TR"){
working = working.parentNode;
}

working.style.visibility = 'hidden';
working.style.display = 'none';
table_index += 1;
self.xmlHttpReq.send(send_query_string());
}
}
} ;
self.xmlHttpReq.send(send_query_string());
return false;
}

Not sure if you want a working solution or hints for the solution.
Presuming the latter (but OK to write for you the first, but it's going
to be my code sorry - with almost nothing left of yours :) :-(

1. "self" is a very bad indentifier because host object "window" has
self-reference property .self
So you are risking to get window reference instead of object reference
- and no error shown, just results far of expected. Just try to call
processtab() as a simple function and put something like:
if (window.XMLHttpRequest) {
// added:
alert(self.navigator);
//
self.xmlHttpReq = new XMLHttpRequest();

Do you really need such ambiguity?

2. xmlHttpReq is created as local variable within processtab() if you
call it as constructor. Or as window property if you call it as regular
function.

You should really create either a singleton (JS-kind, still can be
cloned, but close by functionality):

var xmlHttpReg = {
'reg' : // here XMLHttpRequest object
'send' : // here your send method
};
where later xmlHttpReg.send(args);


or a regular constructor:

function xmlHttpReg() {
this.$ = // XMLHttpRequest object;
this.send = // here your send method
}
where later
glbRequest = new xmlHttpRequest();
glbRequest.send(args);

3. Browser updates the graphics context only after the exit from the
script execution. So you need to give a micro-break in your loop if you
want table rows disappear one by one on each call. That brings the
setTimeout method into the loop, breaks context (because of
incontinence of "this"), a bounch of other interesting things and
finally - the old lore that it is alweays better to write one sub doing
one thing rather then one sub doing 2-3-... things :)

P.S. Do I think that IXMLHTTPRequest / XMLHttpRequest is unnecessary
over-complicated? Yes I do. I would prefer to see something not so
low-level boring. Something like "download" behavior in IE, where you
simply tell what to get, what function to call when done and what
function to call if failed.
But from the other side developers want to eat too, and who will pay
good bucks for "Ajax solution" if anyone can make it in few keypress?
;-)
 
E

Eric S Johansson

VK said:
Not sure if you want a working solution or hints for the solution.
Presuming the latter (but OK to write for you the first, but it's going
to be my code sorry - with almost nothing left of yours :) :-(

yes, I am looking for hints because I'm trying to understand the
specific object but how things are done in JavaScript. It's been years
since I've done any significant coding (reasons too boring to explain)
except for a couple projects in Python.

some of the sins you point out come from copying an example without
understanding the environment fully. based on your subsequent comments,
it's quite clear that the JavaScript documentation on the net is almost
entirely comprised of bad examples and incomplete information.

http://www.degraeve.com/reference/simple-ajax-example.php

1. "self" is a very bad indentifier because host object "window" has
self-reference property .self

I thought that was the case. I was wondering why the example assigned
this to self. What is this then??
So you are risking to get window reference instead of object reference
- and no error shown, just results far of expected. Just try to call
processtab() as a simple function and put something like:
if (window.XMLHttpRequest) {
// added:
alert(self.navigator);
//
self.xmlHttpReq = new XMLHttpRequest();

Do you really need such ambiguity?

no. I would prefer to something like:
request = new XMLHttpRequest();

(by the way, I really hate these bumpy caps. It's really hard to speak
them with speech recognition with all of the said:
2. xmlHttpReq is created as local variable within processtab() if you
call it as constructor. Or as window property if you call it as regular
function.

You should really create either a singleton (JS-kind, still can be
cloned, but close by functionality):

var xmlHttpReg = {
'reg' : // here XMLHttpRequest object
'send' : // here your send method
};
where later xmlHttpReg.send(args);


or a regular constructor:

function xmlHttpReg() {
this.$ = // XMLHttpRequest object;
this.send = // here your send method
}
where later
glbRequest = new xmlHttpRequest();
glbRequest.send(args);

is this stuff documented anywhere? I mean something readable like K&R
because I really don't understand the syntax. It looks like you are
assigning into an associative array? what's wrong with creating an
instance of XMLHttpRequest and just using the methods off of that? If
it needs to persist, assign the instance to a global.
3. Browser updates the graphics context only after the exit from the
script execution. So you need to give a micro-break in your loop if you
want table rows disappear one by one on each call. That brings the
setTimeout method into the loop, breaks context (because of
incontinence of "this"), a bounch of other interesting things and
finally - the old lore that it is alweays better to write one sub doing
one thing rather then one sub doing 2-3-... things :)

okay. This is the point where I've made up my mind to abandon the
project. I don't have the resources to spend any more time on it since
its for an open source project and it's taking me away from billable work.

I was hoping for a way to convert this back to a simple iterative
process but it looks like in order to do so, I would need to either to
go to synchronous mode and all of its problems that I would experience
with process with a total running time of a few seconds to a couple of
minutes or maybe a semaphore between the callback method assigned to
onreadystatechange and the main loop sending the data.

I appreciate the help and it has taught me a lot. I think I'm going to
move instead to shoving all the training requests into a queue on the
server and making the user think the work has been done.
P.S. Do I think that IXMLHTTPRequest / XMLHttpRequest is unnecessary
over-complicated? Yes I do. I would prefer to see something not so
low-level boring. Something like "download" behavior in IE, where you
simply tell what to get, what function to call when done and what
function to call if failed.
But from the other side developers want to eat too, and who will pay
good bucks for "Ajax solution" if anyone can make it in few keypress?
;-)

hey, if I had money and authorization to spend it on a JavaScript
developer, I would do so. But this is an open-source project
(camram.org), it's coming out of my own pocket and I just don't have the
resources be it time or money right now to go any further.

again, many thanks for the help. I do appreciate it and sometimes
knowledge of when to quit is more important than getting to where you
want to be.

---eric
 
V

VK

Eric said:
based on your subsequent comments,
it's quite clear that the JavaScript documentation on the net is almost
entirely comprised of bad examples and incomplete information.

That is close to truth but still an overkill. Look at
<http://www.jibbering.com/faq/#FAQ3_2>

After all JavaScript is not so terribly complicated language, actually
it was designed to be as evident and error tolerable as possible. I
don't want you to leave with a wrong idea about it.

The Pandora box is not in JavaScript itself (at least it is not the
is this stuff documented anywhere? I mean something readable like K&R
because I really don't understand the syntax. It looks like you are
assigning into an associative array? what's wrong with creating an
instance of XMLHttpRequest and just using the methods off of that? If
it needs to persist, assign the instance to a global.

There is some interesting reading in the link I mentioned.
Briefly and plainly in the first case I'm creating global variable
xmlHttpReg holding a reference on pre-made (upon script load) object.
It is the object notation which is equal to hashtable notation because
in JavaScript these are the same:
var myObject = {'method' : function(){} , 'field' : 'foo'};
var myHash = {''key1' : 'value1', 'key2' : 'value2'};
- JavaScript really doesn't care.

So this object instantiated by itself and you can use it right away:
xmlHttpReg.someMethod();

In the second case I'm creating function-constructor, so you need to
instantiate your object first:
var myQuery = new xmlHttpReg();
myQuery.someMethod();
okay. This is the point where I've made up my mind to abandon the
project. I don't have the resources to spend any more time on it since
its for an open source project and it's taking me away from billable work.

I was hoping for a way to convert this back to a simple iterative
process but it looks like in order to do so, I would need to either to
go to synchronous mode and all of its problems that I would experience
with process with a total running time of a few seconds to a couple of
minutes or maybe a semaphore between the callback method assigned to
onreadystatechange and the main loop sending the data.

There is nothing wrong in your model concept, just the actual
implementation hits some background problems like delayed graphics
context update or absence of real threads in JavaScript. It's all
doable. I actually have to implement something similar in my own
project. I'll post the code when ready in this thread - but no
deadline. ;-)
again, many thanks for the help. I do appreciate it and sometimes
knowledge of when to quit is more important than getting to where you
want to be.

What can be more important than properly working program ?!? :-D
 
E

Eric S Johansson

VK said:
That is close to truth but still an overkill.

fair enough. Let's just say that the road to bad information is paved
with Google references.


great. I've started onto the ref docs. so it should be relatively
fluent by the time you reply to my next question.
After all JavaScript is not so terribly complicated language, actually
it was designed to be as evident and error tolerable as possible. I
don't want you to leave with a wrong idea about it.

from what I've read so far, I'm starting to agree with you. It's just
that finding the right documentation is at times difficult given all of
the attempting to be helpful web pages cluttering the search space.
The Pandora box is not in JavaScript itself (at least it is not the


There is some interesting reading in the link I mentioned.
Briefly and plainly in the first case I'm creating global variable
xmlHttpReg holding a reference on pre-made (upon script load) object.
It is the object notation which is equal to hashtable notation because
in JavaScript these are the same:
var myObject = {'method' : function(){} , 'field' : 'foo'};
var myHash = {''key1' : 'value1', 'key2' : 'value2'};
- JavaScript really doesn't care.

So this object instantiated by itself and you can use it right away:
xmlHttpReg.someMethod();

In the second case I'm creating function-constructor, so you need to
instantiate your object first:
var myQuery = new xmlHttpReg();
myQuery.someMethod();

I think I now understand. so I should be able to just do something like:

requester = new XMLHttpRequest()

and then use

requester.open(...)
requester.send(...)

because I don't believe there's any need to stick an instance of
XMLHttpRequest into another object. I think...
There is nothing wrong in your model concept, just the actual
implementation hits some background problems like delayed graphics
context update or absence of real threads in JavaScript. It's all
doable. I actually have to implement something similar in my own
project. I'll post the code when ready in this thread - but no
deadline. ;-)

understood. you now, I would love to incorporate stuff like this into
Akasha (small-scale web development framework I've built) I just need to
figure out the right way of expressing the the capabilities of
JavaScript+dom at a high/macro level.

What can be more important than properly working program ?!? :-D

slow roasting a chicken covered with all sorts of herbs in a barbecue
restoring a Schupmann telescope back to full functionality
reading a good book
writing a good book (much harder than programming and pays less)
learning how to make a *good* pie crust (hint, use 2 types of fat
butter/lard or butter/shortening and keep it really cold)

:)

--- eric
 
T

Thomas 'PointedEars' Lahn

Eric said:
VK said:
Or you can monitor readyState over onreadystatechange and launch the
next request as soon as the previous is done.

I've tried this and I've enclosed a test function I was using for
experimenting with this technique and learning JavaScript at the same
time. I'm sure you'll be able to give me grief over lots of things.
[...]

Which part of my followup did you not understand?


PointedEars
 
R

Randy Webb

Thomas 'PointedEars' Lahn said the following on 1/27/2006 8:18 PM:
Eric said:
VK said:
Or you can monitor readyState over onreadystatechange and launch the
next request as soon as the previous is done.
I've tried this and I've enclosed a test function I was using for
experimenting with this technique and learning JavaScript at the same
time. I'm sure you'll be able to give me grief over lots of things.
[...]

Which part of my followup did you not understand?

Probably beginning at the point where you started quoting and ended
about the point where your post says "Thomas".
 
E

Eric S Johansson

since you asked me in another message what part of your post I didn't
understand, I felt like the response missed I needed to know in
response my query. So I initially ignored it and followed more
productive avenues. it wasn't until I learned more about the JavaScript
environment that I was able to take advantage of what you had written.

Obviously we've gotten off on the wrong foot. I apologize for my part
of that and here's my commentary on your response.
Then your object model is flawed or does not fit the approach.

In either case, it's a function of documentation. My object model is
based on what I know about object-oriented design. other people have
pointed me to some useful forms of documentation which which I am
reading through.

I personally don't think my object model is flawed. It's a
tried-and-true pattern used by software developers for decades. my
implementation of the model does work in synchronous mode with the only
failure being that it won't update the display. Yes I know that
synchronous transactions do lock up the browser but there should be some
way to tell it to refresh based on the current DOM state. Again, I
haven't found the documentation telling me how to do this.

as for asynchronous mode, it works for the first loop but doesn't
trigger off all the event handlers for the second loop. (fixed, see below)
It is a possibility that reduces responsiveness of the client but not
necessarily one that also reduces server load.

in my case it does reduce server load because it processes all of the
element of a given client sequentially. This allows me to have a
greater number of clients performing the same type of tasks without
hammering the server completely.
No, it is enough if you change the request parameters, e.g. if the target
resource changes, call the open() method of the XMLHttpRequest object with
the different resource URI again and, after that, assign the event
listener(s) again.

my experience has been that since I change post arguments with every
call, I need to restart the loop with an open on through send. is this
anomalous?
It is the `readystatechange' event that is firing and the "semaphore"
(IMHO "flag" is the better word) for that is the `onreadystatechange'
event handler calling the assigned event listener, so no. Just assign
a different event listener when needed.

I interpret what you are saying as once I have set onreadystatechange,
it will stay forever as long as the object it is part of persists. is
this correct?
Although I do not understand why more than one request is necessary
here, the following asynchronous approach works in Firefox 1.5/Linux:

*thank you* for forcing me to go through this again because I just found
the typo that was causing one of my problems. I swear to g*d I looked
at your examples at least four or five times and my code four or five
times and it just didn't pop out until now.

now that I can do multiple requests as I wanted, my next challenge is
updating the display. I can make table rows go away but I can't get the
next one to change color. It's not a huge deal and I can live with it
as it is. It's just that color changing would be a good thing from an
HCI perspective.

thank you again and I appreciate your patience while I climb the
JavaScript learning curve.

---eric
 
T

Thomas 'PointedEars' Lahn

Eric said:
In either case, it's a function of documentation. My object model is
based on what I know about object-oriented design. other people have
pointed me to some useful forms of documentation which which I am
reading through.

I personally don't think my object model is flawed. It's a
tried-and-true pattern used by software developers for decades. my
implementation of the model does work in synchronous mode with the only
failure being that it won't update the display. Yes I know that
synchronous transactions do lock up the browser but there should be some
way to tell it to refresh based on the current DOM state. Again, I
haven't found the documentation telling me how to do this.

It is hard to do it justice without you showing any relevant code.
as for asynchronous mode, it works for the first loop but doesn't
trigger off all the event handlers for the second loop. (fixed, see below)
ACK


in my case it does reduce server load because it processes all of the
element of a given client sequentially. This allows me to have a
greater number of clients performing the same type of tasks without
hammering the server completely.

You are not making any sense. Whether you do asynchronous requests one
after another or synchronous requests one after another should not have any
impact on server load, no matter the number of clients, because the server
receives the same sequence of requests and sends the same sequence of
responses, in approximately the same time. AIUI, the choice between
sequential synchronous and sequential asynchronous HTTP requests affects
the resulting responsiveness of the client only. In fact, _parallel_
asynchronous requests (which do not happen here due to your specifications)
_increase_ the network and server load compared to (necessarily) sequential
synchronous requests in favor of overall faster responses.
my experience has been that since I change post arguments with every
call, I need to restart the loop with an open on through send. is this
anomalous?

I do not understand what you mean by loop. There is no loop involved so
far. However, every time you call open(), you have to assign the event
listener for the `onreadystatechange' event handler afterwards again.
I interpret what you are saying as once I have set onreadystatechange,
it will stay forever as long as the object it is part of persists. is
this correct?

No, I wrote "_when_ needed" on purpose :) As I said, the event listeners
are reset if you call certain methods of the XMLHttpRequest object, such
as open(). Details can be found in the IXMLHTTPRequest and XMLHttpRequest
references:

<URL:http://msdn.microsoft.com/library/en-us/xmlsdk/html/7924f6be-c035-411f-acd2-79de7a711b38.asp>
Although I do not understand why more than one request is necessary
here, the following asynchronous approach works in Firefox 1.5/Linux:

*thank you* for forcing me to go through this again because I just found
the typo that was causing one of my problems. [...]

You're welcome :)
now that I can do multiple requests as I wanted, my next challenge is
updating the display. I can make table rows go away but I can't get the
next one to change color. It's not a huge deal and I can live with it
as it is. It's just that color changing would be a good thing from an
HCI perspective.

Apply a (Cascading) StyleSheet (CSS), e.g. with

trRef.style.color = "white";
trRef.style.backgroundColor = "red";

If that does not help, show some code that does not work.
See also <URL:http://jibbering.com/faq/#FAQ4_43>.


HTH

PointedEars
 
R

Richard Cornford

VK said:
Eric S Johansson wrote:
1. "self" is a very bad indentifier because host object
"window" has self-reference property .self

Rubbish. The global object in a browsers has numerous properties with
names that have been chosen to convey meaning related to their purpose.
For example, it has a "length" property. Would you say that if another
object had a property that was conceptually a length that property
should not be named "length" because the global object already has a
property with that name?
So you are risking to get window reference instead of object
reference - and no error shown, just results far of expected.

Nonsense. Unqualified identifiers are resolved against the scope chain,
and Identifiers used to declare local variables result in the creation
of named properties of the Variable/Activation object sitting at the top
of scope chain for the function's execution context. The global object
is the last object on a function's scope chain so the Identifier -
self - will _always_ be resolved as the property of the
Variable/Activation object because that object is examined before the
global object during Identifier resolution.
Just try to call processtab() as a simple function
and put something like:

That has nothing to do with the resolution of the Identifier - self -.
That Identifier will be resolved as the local variable from any code
within the function body. The difference between executing the function
as a global function rather than as a constructor or object method is
the value of the - this - keyword.
if (window.XMLHttpRequest) {
// added:
alert(self.navigator);
//
self.xmlHttpReq = new XMLHttpRequest();

Do you really need such ambiguity?

If there is any ambiguity it is not in the resolution of the
Identifier - self -, that always resolves as a reference to the same
property of the Variable/Activation object at the top of the scope chain
for the function's execution context.

The 'ambiguity' you perceive relating to the use of - self - is a result
of the value of - self - being assigned as the value of - this -, and is
probably only a manifestation of your ongoing failure to understand how
javascript determines the - this - value based entirely upon how a
function is called (and regardless of having this explained to you on
numerous occasions).

If the function is called as a global function then - this - will be a
reference to the global object, and so the local variable - self - will
also be a reference to the global object. Because the property of the
global object with the name "self" is itself a reference to the global
object, without an understanding of how javascript behaves, you might
(apparently do) perceive ambiguity in the resolution of the - self -
identifier, as the properties of the object referred to by the local
variable - self - will be the same as the properties of the global
object. But in reality all you have done is allow the misconceptions
that are the inevitable result of your technical ignorance to re-enforce
your misconceptions.
2. xmlHttpReq is created as local variable within
processtab() if you call it as constructor.

No it is not. Local variables are created within a function by the use
of the - var - keyword. "xmlHttpReq" is created as a named property of
whatever object is referred to by the - self - local variable.
Or as window property if you
call it as regular function.

All of this noise, misdirection and misconception boils down to the
relatively simple conclusion that if you use - this - in a function you
need to understand how the way in which the function is used determines
the value of - this -.
You should really ...
<snip>

What is the point of your attempting to give advice about the best way
writing javascript when you don't even understand the basics of
javascript? How do you expect to be able to see the optimum
implementation strategy when you cannot even recognise a local variable?

Richard.
 
T

Thomas 'PointedEars' Lahn

Thomas said:
[...] Whether you do asynchronous requests one after another or
synchronous requests one after another should not have any impact on
server load, no matter the number of clients, because the server receives
the same sequence of requests and sends the same sequence of responses, in
approximately the same time. AIUI, the choice between sequential
synchronous and sequential asynchronous HTTP requests affects the
resulting responsiveness of the client only. In fact, _parallel_
asynchronous requests (which do not happen here due to your
specifications) _increase_ the network and server load compared to
(necessarily) sequential synchronous requests in favor of overall faster
responses.

Due to the ambiguous nature of the word "response", I feel compelled to
clarify my last sentence in order to avoid confusion. Of course it is _not
one_ /server/ response that is meant here; the server does respond to one
asynchronous request with the same speed it would to one synchronous
request.

What is meant is that the _client_ response is faster, i.e. the
responsiveness of the client and its UI is increased when making
asynchronous XMLHTTP requests instead of synchronous ones. What is also
meant is that the server is able to handle several parallel requests from
the same client (possible with asynchronous XMLHTTP requests) faster in
total than a sequence of consecutive requests from the same client, with
the drawback that the network and server load is higher with the former
than with the latter.


PointedEars
 
E

Eric S Johansson

Thomas said:
It is hard to do it justice without you showing any relevant code.

apologies. I thought I had posted the URLs enough that they were
annoying. long story short, I think I found most of the problems and I
now have a reasonably close approximation of what I was looking for.

http://harvee.org/files/correct.html
http://harvee.org/files/camram.js

it's a working demo. It doesn't really do anything with the real
application. It just calls a CGI with a two second delay in the CGI.

this was a result of changing code as I got new knowledge but not quite
enough to do the right thing.

You are not making any sense. Whether you do asynchronous requests one
after another or synchronous requests one after another should not have any
impact on server load, no matter the number of clients, because the server
receives the same sequence of requests and sends the same sequence of
responses, in approximately the same time. AIUI, the choice between
sequential synchronous and sequential asynchronous HTTP requests affects
the resulting responsiveness of the client only. In fact, _parallel_
asynchronous requests (which do not happen here due to your specifications)
_increase_ the network and server load compared to (necessarily) sequential
synchronous requests in favor of overall faster responses.


again, I think we were not understanding each other properly. My
interpretation of what you had suggested with asynchronous requests
would end up with a series of requests in parallel. Which is why I said
that I want to do them sequentially to keep the load low. the reason I
thought that was that I didn't see any discussion of a request moderator
(semaphore, busy loop etc. to wait for the first request to finish
before continuing on to the next. Again, with subsequently acquired
knowledge, I was able to see more clearly what you were trying to say.

I do not understand what you mean by loop. There is no loop involved so
far. However, every time you call open(), you have to assign the event
listener for the `onreadystatechange' event handler afterwards again.

whether you see it or not, there is a loop. Loops can take the form of
a classic for or while loop or they can come out of an event driven
system where it the event performs the work required to retrigger the
event. Then when the event triggers again, the loop is restarted.
iterative processes take many forms.

this does raise a second question which is do I need to keep calling
open if I'm using a post operation and am only changing the argument to
the post.
No, I wrote "_when_ needed" on purpose :) As I said, the event listeners
are reset if you call certain methods of the XMLHttpRequest object, such
as open(). Details can be found in the IXMLHTTPRequest and XMLHttpRequest
references:

<URL:http://msdn.microsoft.com/library/en-us/xmlsdk/html/7924f6be-c035-411f-acd2-79de7a711b38.asp>
<URL:http://xulplanet.com/references/objref/XMLHttpRequest.html>

thank you. Those are good-looking references.

Apply a (Cascading) StyleSheet (CSS), e.g. with

trRef.style.color = "white";
trRef.style.backgroundColor = "red";

If that does not help, show some code that does not work.
See also <URL:http://jibbering.com/faq/#FAQ4_43>.

I was able to figure that out all my own and I discovered that the
change would not be visible until called XMLHttpRequest methods. Don't
fully understand why or when but I'm sure that knowledge will come
eventually.

---eric
 
T

Thomas 'PointedEars' Lahn

Eric said:
Thomas said:
It is hard to do it justice without you showing any relevant code.

[...] long story short, I think I found most of the problems and I
now have a reasonably close approximation of what I was looking for.

http://harvee.org/files/correct.html
http://harvee.org/files/camram.js

it's a working demo. It doesn't really do anything with the real
application. It just calls a CGI with a two second delay in the CGI.

Frankly, I do not understand why you make a new asynchronous request for
each row via processtab(). This alone increases network and server load
by orders of magnitude compared to a recordset-based approach.

At least you are declaring your variables.

Please read my later clarification in if you have not yet, before discussing the above further.
again, I think we were not understanding each other properly. My
interpretation of what you had suggested with asynchronous requests
would end up with a series of requests in parallel.

It does not, I implemented it as you requested it to be. The first
connection is opened [open()], the first event listener is assigned
(onreadystatechange = ...) and the first request is initiated [send()].
When the ready-state of the first request changes, the previously assigned
(first) event listener is called by the UA via the `onreadystatechange'
handler. If the request has been made (readyState == 4) and is successful
(status == 200), the second connection is opened (which can be the first
connection reused), the second event listener is assigned and the second
request is initiated. The second event listener is called when the
ready-state of the second request changes and so on.
[...]
I do not understand what you mean by loop. There is no loop involved so
far. However, every time you call open(), you have to assign the event
listener for the `onreadystatechange' event handler afterwards again.

whether you see it or not, there is a loop. Loops can take the form of
a classic for or while loop or they can come out of an event driven
system where it the event performs the work required to retrigger the
event. Then when the event triggers again, the loop is restarted.
iterative processes take many forms.

In computer science, a loop is defined as a _control structure_ to repeat
evaluation of the _same_ code. One event listener _redefining_ itself
certainly does not qualify as a loop.
this does raise a second question which is do I need to keep calling
open if I'm using a post operation and am only changing the argument
to the post.

If the request method, request URI and sync/async method do not change, you
do not have to call open() again. However, as send() is specified and
implemented as a method that clears the event listeners, you will have to
reassign them before making further requests.
I was able to figure that out all my own and I discovered that the
change would not be visible until called XMLHttpRequest methods.
Don't fully understand why or when but I'm sure that knowledge will
come eventually.

The most likely reason for this is that JS/ECMAScript is single-threaded.


PointedEars
 
V

VK

Thomas said:
The most likely reason for this is that JS/ECMAScript is single-threaded.

Not really - but what you can archieve by simply "new Thread()" in say
Java needs a lot of low level work in JavaScript. I know that some
programmers do think that they touch some "statue of Real Programming"
by using threads but really they are using the same
setTimeout/onreadystatechange just moved out of their consideration.
The real trap in the OP's posed question is to update the DOM within a
loop AND to initiate Ajax (sorry to say) request within the same loop.
This problen has been posed (in different interesting forms) in this
group within the last few month. I'm going to try to answer this
question at the best of my limited abilitites - despite that my final
aim is to replace Ajax with something much more user friendly and
universal.

********
I am not the best person knowing JavaScript or ECMAScript. Any person
posting in this group is presumably knowing more than I do.
********
 
T

Thomas 'PointedEars' Lahn

VK said:
Thomas said:
The most likely reason for this is that JS/ECMAScript is single-threaded.

Not really [...]

Please do not try to talk about something that you have no clue about.
JS/ECMAScript is single-threaded.


PointedEars
 
V

VK

Thomas said:
VK said:
Thomas said:
The most likely reason for this is that JS/ECMAScript is single-threaded.

Not really [...]

Please do not try to talk about something that you have no clue about.
JS/ECMAScript is single-threaded.

To OP (Original Poster): please do not get upset, that's the way Usenet
works, you're forced to talk with the God and Satan at once (not saying
I'm anyone of them, but XMLHttpRequest links were good).
 

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,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top