[Prototype-core] Ajax.Request.getStatus() new in 1.6

195 views
Skip to first unread message

Ken Snyder

unread,
Sep 6, 2007, 6:56:58 PM9/6/07
to prototy...@googlegroups.com
I see that Sam added a new function to 1.6
svn--Ajax.Request.getStatus(). I'm curious because I just did some
research on status codes when the network connection is dropped and
wondered if any of you (especially Sam) have any additional insight.

To summarize the situation: when ajax calls encounter network errors,
FF2 throws an exception when reading transport.status; Opera 9 and
Safari 3 show transport.status = 0; IE6 and IE7 show transport.status =
12029 (or one of 5 other values).

I see the new getStatus() function now accounts for exceptions and
transport.status of 0 (O9, S3, FF2), and thus has an "on0" callback. I
propose adding IE support and changing the callback name to
"onNetworkError".

Here is the code (I will submit a patch):


Ajax.Request = {
...
success: function() {
var status = this.getStatus();
return status != 'NetworkError' && status >= 200 && status < 300;
},

getStatus: function() {
try {
var status = this.transport.status;
if ([0, 1223, 12002, 12029, 12030, 12031, 12152].include(status))
return 'NetworkError';
return status;
} catch(e) {
// allow callback functions to access properties without
generating an Exception
this.transport = {};
return 'NetworkError';
}
},
...

Network error scenarios:
FF - throws exception
IE6/7 - transport.status = 12029 (or other, see below)
S3 - transport.status = 0
O9 - transport.status = 0

IE status Error codes:
1223 : Client canceled request
12002: Server timeout
12029: Dropped connection
12030: Dropped connection
12031: Dropped connection
12152: Connection closed by server

Also of note is that FF 1.x returns a status of 200 on network errors
(no Exception), so the developer is left to see that the response is
empty to know of a failure.

references:
http://dev.rubyonrails.org/changeset/7265
http://developer.yahoo.com/yui/docs/connection.js.html
http://www.thescripts.com/forum/thread573352.html
http://trac.dojotoolkit.org/ticket/2418


- Ken Snyder

Tobie Langel

unread,
Sep 7, 2007, 7:30:07 AM9/7/07
to Prototype: Core
Hi Ken,

I didn't push the getStatus method further than that because there are
some issues with the file protocol in Safari (status is always equal
to 0 in that case if I remember well).

Proper support for the file protocol is something I'd like to have for
1.6 final.

It implies rewritting Ajax.getTransport to deal with IE7's poor xhr
object implementation.

If we want to properly handle network exceptions, we might need to
special case the getStatus method for requests using the file
protocol.

Regarding your suggestion for an onNetworkError callback, have you
considered throwing a NetworkError exception instead and catching it
via the onException callback ? I'm unsure which solution is better,
thoughts?

Regards,

Tobie

jdalton

unread,
Sep 7, 2007, 9:22:20 AM9/7/07
to Prototype: Core

I like the idea of having one handle for those cryptic error codes.

Would onNetworkError be different than onException ( does the
onException get called as well??)

Ken Snyder

unread,
Sep 7, 2007, 11:47:12 AM9/7/07
to prototy...@googlegroups.com
In my current implementation, a network error triggers onNetworkError,
onLoaded, onComplete, then onFailure. I find the onNetworkError to be
important because the developer can stop sending ajax requests until the
user indicates that a connection has been re-established. Or, perhaps
connection-testing ajax requests can be sent on a periodic basis.

Throwing an exception is fine as long as the exception is clearly
distinguishable from other exceptions. A custom onNetworkError callback
seems more useful than having to test the exception.

So Tobie, how would you use the file protocol for an ajax request? For
including a client's local file with static content? Is there any other
indication that it is a local file other than the url having "file*" ?

- Ken

Tobie Langel

unread,
Sep 8, 2007, 2:29:07 PM9/8/07
to Prototype: Core
> So Tobie, how would you use the file protocol for an ajax request?

It's mainly a backwards compatibility issue (plus it can be useful for
testing purposes).

Ken Snyder

unread,
Sep 10, 2007, 6:09:06 PM9/10/07
to prototy...@googlegroups.com
After some testing, I am seeing how using "onNetworkError" is not
helpful since some network errors (such as dropping vpn connection)
produce exceptions anyway. It makes more sense if all network errors
trigger the "onException" callback.

As far as local file support: Tobie, would the folllowing "isLocalUrl"
test be sufficient to test if the file protocol is used? I'm not real
familiar with file protocol behavior, especially across OSs and Browsers.

I'm just thinking it would be best to submit a patch that addresses both
issues since you mention that requesting local files looks like a
network error due to transport.status = 0.

- Ken Snyder

Ajax.Request = Class.create(Ajax.Base, {
...
request: function(url) {
this.url = url;

// we have a local request if:
// the url begins with "file" OR
// the window url begins with "file" and the url does not contain
"://"
this.isLocalUrl = (this.url.indexOf('file') === 0 || (
window.location.href.indexOf('file') === 0 &&
this.url.indexOf('://') == -1
));

this.method = this.options.method;
...
}
});

Ken Snyder

unread,
Sep 12, 2007, 1:02:32 PM9/12/07
to prototy...@googlegroups.com
Tobie,

Looking at John Resig's jQuery, I see that the file protocol is
considered. However, it doesn't account for URLs which have links to
static content as you mentioned might be used in testing.

httpSuccess: function( r ) {
try {
return !r.status && location.protocol == "file:" ||
( r.status >= 200 && r.status < 300 ) || r.status == 304 ||
jQuery.browser.safari && r.status == undefined;
} catch(e){}
return false;
},

Below is an untested patch. Is it in line with your vision of
functionality? It allows URLs to call local files, eliminates the "on0"
callback and calls "onSuccess" for both local files and successful
requests. My question is: Is it possible to detect when local files
fail to load?

- Ken Snyder

Index: ajax.js
===================================================================
--- ajax.js (revision 7468)
+++ ajax.js (working copy)
@@ -74,6 +74,9 @@



request: function(url) {
this.url = url;

+ this.isLocalUrl = this.url.indexOf('file:') === 0 ||
+ (location.protocol == 'file:' && this.url.indexOf('://') == -1);
this.method = this.options.method;
var params = Object.clone(this.options.parameters);

@@ -162,24 +165,32 @@



success: function() {
var status = this.getStatus();

- return !status || (status >= 200 && status < 300);
+ return status == 304 || (status >= 200 && status < 300) ||
(this.isLocalUrl && !status);
},
-
+
getStatus: function() {
try {
- return this.transport.status || 0;
- } catch (e) { return 0 }
- },
-
+ var status = this.transport.status;
+ if (this.isLocalUrl)
+ return 200;
+ if ([1223, 12002, 12029, 12030, 12031, 12152].member(status))
+ return 0;
+ return status;
+ } catch(e) {
+ return 0;
+ }
+ },
+
respondToReadyState: function(readyState) {
- var state = Ajax.Request.Events[readyState], response = new
Ajax.Response(this);
+ var state = Ajax.Request.Events[readyState];
+ var json = this.evalJSON();

if (state == 'Complete') {
try {
this._complete = true;
- (this.options['on' + response.status]
+ (this.options['on' + (this.getStatus() || 'Exception')]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(response, response.headerJSON);
+ || Prototype.emptyFunction)(this.transport, json);
} catch (e) {
this.dispatchException(e);
}


Reply all
Reply to author
Forward
0 new messages