D
David Mark
How to Create an XHR (Ajax) Object
var xhrCreated;
// As always, shorthand feature detection for example--use
isHostMethod in this case
// Degrades in IE 6-
if (this.XMLHttpRequest)
// Use try-catch as this host object may explode on creation
try {
var x = new XMLHttpRequest();
xhrCreated = true;
} catch(e) {
}
}
if (xhrCreated) {
var createXhrObject = function() {
return new XMLHttpRequest();
};
}
if (createXhrObject) {
// Put app that must create XHR objects here
}
Thanks to IE, you can't assume that file protocol will work. Put
something like this at the top of your xhrSend function:-
if (uri.slice(0, 5) == 'file:') {
throw new Error('No file prototcol requests with this rendition!');
}
....and take it out on deployment. Pattern of builder should be clear
at this point: checkboxes for degradation points and other questions
of context, plus a checkbox for "debug version", which includes lots
of additional throws to keep the developers honest. It should be
obvious that the build flavor must be settled on at *design* time, not
at deployment. All you do at deployment is uncheck "debug version"
and get the same exact code you developed with, minus the cattle
prods.
Contrast this with breaking up all of your supporting code into tiny
bits, loading them dynamically with script and dealing with all of the
related complications, then running all of these bits through a
"compiler" to piece together something that might approximate what you
encountered during development. Doesn't matter if you release to QA
testers or directly to an unsuspecting public (the norm), such a
strategy is obviously error-prone and self-defeating (not to mention
silly). Error in line 1!
But I digress. What about IE 7 and under? Same pattern, different
objects (ActiveX to be specific). If you must provide an "Ajax
experience" for those stuck with these older IE versions, put the
ActiveX crap in a script inside conditional comments.
I'm thinking that's another option for the builder (splitting the
build in two, with one file to be included in IE conditional
comments). If that's too hard for the average Web developer to deal
with, it could also spit out an HTML template that includes the two
scripts. They will certainly need that for the next installment,
which is dealing with the onload "problem".
In my experience, such IE fallback scripts are usually aimed at 8 and
under, but this one is only needed for 6 and under, so do this:-
if (!createXhrObject) {
// Create ActiveX rendition here
}
....or break it out into another file, aimed only at IE 7 and under.
If you need to use the "file" protocol, drop the check for
createXhrObject and set that reference to null before starting the
ActiveX tests (In IE, you need the ActiveX version of XHR to do "file"
requests).
It's worth noting that much of the feature detection/testing is
unneeded in these IE fallback renditions if they are to be included
exclusively in conditional comments. I suppose that's another option
for the builder.
As for sending a request and reacting to the asynchronous (and they
must *always* be asynchronous) callbacks, I'll leave that for another
time. Look into the send method of the Requester object (in My
Library) for the basics. Having used that object (one of the small
bits of My Library that I actually still use) on some recent projects,
I noticed a design mistake: there should never have been an "oncancel"
callback and there should have been an "ontimeout" callback (currently
"oncancel" serves both). The cancel operation is programmatic and the
timeout is not. So the former doesn't need a callback as it is rarely
useful to call your code back due to its own actions. In this case,
it can lead to some ugly logic in the "oncancel" callback (to
determine whether the call is a result of a timeout or not).
What can you expect from the typical do-everything library or
framework? Again, God only knows. For the longest time, jQuery
didn't account for the fact that the ActiveX objects could blow up (no
try-catch until about the fifth version). Things like Dojo and YUI
use browser sniffing and such projects are too large to recover from
such mistakes; there's just not enough interested parties to go back
and rewrite all of the botched code. I tried to fix Dojo once, but
the authors were steadfastly opposed to "patches" that involved more
than a few lines of code at a time. I don't know if that was because
of general delusion or just the fear of appearing incompetent, but at
that rate, it would have taken thirty years to shake all of the bugs
out. So their developers' egos were saved, but when IE 9 hit, every
Dojo application ever written (all ten) fell apart.
Interestingly enough, Dojo's XHR "module" actually requires their
botched query module. That's the "best minds in the industry for
you": not thinking beyond today at all; and not thinking much today
either. How many versions of Dojo and YUI actually turned out to be
reusable (beyond the brand name)? Redo-able is what they meant.
http://www.cinsoft.net/
http://twitter.com/cinsoft
http://jsperf.com/browse/david-mark
var xhrCreated;
// As always, shorthand feature detection for example--use
isHostMethod in this case
// Degrades in IE 6-
if (this.XMLHttpRequest)
// Use try-catch as this host object may explode on creation
try {
var x = new XMLHttpRequest();
xhrCreated = true;
} catch(e) {
}
}
if (xhrCreated) {
var createXhrObject = function() {
return new XMLHttpRequest();
};
}
if (createXhrObject) {
// Put app that must create XHR objects here
}
Thanks to IE, you can't assume that file protocol will work. Put
something like this at the top of your xhrSend function:-
if (uri.slice(0, 5) == 'file:') {
throw new Error('No file prototcol requests with this rendition!');
}
....and take it out on deployment. Pattern of builder should be clear
at this point: checkboxes for degradation points and other questions
of context, plus a checkbox for "debug version", which includes lots
of additional throws to keep the developers honest. It should be
obvious that the build flavor must be settled on at *design* time, not
at deployment. All you do at deployment is uncheck "debug version"
and get the same exact code you developed with, minus the cattle
prods.
Contrast this with breaking up all of your supporting code into tiny
bits, loading them dynamically with script and dealing with all of the
related complications, then running all of these bits through a
"compiler" to piece together something that might approximate what you
encountered during development. Doesn't matter if you release to QA
testers or directly to an unsuspecting public (the norm), such a
strategy is obviously error-prone and self-defeating (not to mention
silly). Error in line 1!
But I digress. What about IE 7 and under? Same pattern, different
objects (ActiveX to be specific). If you must provide an "Ajax
experience" for those stuck with these older IE versions, put the
ActiveX crap in a script inside conditional comments.
I'm thinking that's another option for the builder (splitting the
build in two, with one file to be included in IE conditional
comments). If that's too hard for the average Web developer to deal
with, it could also spit out an HTML template that includes the two
scripts. They will certainly need that for the next installment,
which is dealing with the onload "problem".
In my experience, such IE fallback scripts are usually aimed at 8 and
under, but this one is only needed for 6 and under, so do this:-
if (!createXhrObject) {
// Create ActiveX rendition here
}
....or break it out into another file, aimed only at IE 7 and under.
If you need to use the "file" protocol, drop the check for
createXhrObject and set that reference to null before starting the
ActiveX tests (In IE, you need the ActiveX version of XHR to do "file"
requests).
It's worth noting that much of the feature detection/testing is
unneeded in these IE fallback renditions if they are to be included
exclusively in conditional comments. I suppose that's another option
for the builder.
As for sending a request and reacting to the asynchronous (and they
must *always* be asynchronous) callbacks, I'll leave that for another
time. Look into the send method of the Requester object (in My
Library) for the basics. Having used that object (one of the small
bits of My Library that I actually still use) on some recent projects,
I noticed a design mistake: there should never have been an "oncancel"
callback and there should have been an "ontimeout" callback (currently
"oncancel" serves both). The cancel operation is programmatic and the
timeout is not. So the former doesn't need a callback as it is rarely
useful to call your code back due to its own actions. In this case,
it can lead to some ugly logic in the "oncancel" callback (to
determine whether the call is a result of a timeout or not).
What can you expect from the typical do-everything library or
framework? Again, God only knows. For the longest time, jQuery
didn't account for the fact that the ActiveX objects could blow up (no
try-catch until about the fifth version). Things like Dojo and YUI
use browser sniffing and such projects are too large to recover from
such mistakes; there's just not enough interested parties to go back
and rewrite all of the botched code. I tried to fix Dojo once, but
the authors were steadfastly opposed to "patches" that involved more
than a few lines of code at a time. I don't know if that was because
of general delusion or just the fear of appearing incompetent, but at
that rate, it would have taken thirty years to shake all of the bugs
out. So their developers' egos were saved, but when IE 9 hit, every
Dojo application ever written (all ten) fell apart.
Interestingly enough, Dojo's XHR "module" actually requires their
botched query module. That's the "best minds in the industry for
you": not thinking beyond today at all; and not thinking much today
either. How many versions of Dojo and YUI actually turned out to be
reusable (beyond the brand name)? Redo-able is what they meant.
http://www.cinsoft.net/
http://twitter.com/cinsoft
http://jsperf.com/browse/david-mark