-
-
Save dmethvin/43ffd1c743554e5c50ae to your computer and use it in GitHub Desktop.
| // Node-like signature with single callback, returns the XHR | |
| $.xhrcb( url: String, complete: Function( err: Error, xhr: XHR, options: Object ) ): XHR; | |
| $.xhrcb( options: Object, complete: Function( err: Error, xhr: XHR, options: Object ) ): XHR; | |
| // Returns a Promise, throws an error if no Promise or shim | |
| $.xhr( options: Object ): Promise | |
| // See ticket http://bugs.jquery.com/ticket/14509 for `options` | |
| // Thoughts: | |
| // * `options` should not include callbacks! Expose functionality | |
| // by passing in functions or chaining Promise. | |
| // * May need to allow beforeSend option as an escape hatch. | |
| // * `err` here does not try to judge success by HTTP status, that can | |
| // be done at another level (see examples below). | |
| // * I've separated out the entity data from the url data to avoid needing | |
| // to guess where it goes and allow BOTH to be used in a request. | |
| // ------------------- EXAMPLES ------------------- | |
| // Basic GET request, using complete callback | |
| $.xhrcb({ url: "/user/1234" }, function( err, xhr, options ) { | |
| if ( err || xhr.status !== 200 ) { | |
| // Something went wrong, examine err and xhr | |
| return; | |
| } | |
| var user = $.parseJSON( xhr.responseText ); | |
| // Note that `user` could be `null` here... | |
| console.log( "Name: ", user.name ); | |
| }); | |
| // Use helper to break into $.ajax-like error/success callbacks | |
| $.xhrcb("/user/1234", $.xhr.toSuccessError( | |
| function( user, xhr, options ) { | |
| console.log( "Name: ", user.name ); | |
| }, | |
| function( err, xhr, options ) { | |
| console.log( "Error: " + err + " " + xhr.status ); | |
| } | |
| )); | |
| // GET request known to return JSON, using Promise | |
| $.xhr( "/user/123/" ) | |
| .then( $.xhr.toJSON ) | |
| .then( function( user ) { | |
| console.log( "Name: ", user.name ); | |
| }) | |
| .catch( function( err ) { | |
| console.error( "Error: ", err ); | |
| }); | |
| // POST request where we only care about success | |
| $.xhr({ | |
| url: "/user/create/", | |
| method: "POST", | |
| body: { name: "Dave", awesome: true, city: "Columbia" } | |
| }) | |
| .then( | |
| function() { | |
| console.log( "User created" ); | |
| }, | |
| function( err ) { | |
| console.error( err.message ); | |
| } | |
| ); | |
| // POST with a single retry if the server is busy. Assume we add the xhr | |
| // and options as a property of the Error object so it can be accessed. | |
| $.xhr({ | |
| url: "/user/create/", | |
| method: "POST", | |
| body: { name: "Dave", awesome: true, city: "Columbia" } | |
| }) | |
| .catch( function( err ) { | |
| // If the server was busy, retry once | |
| if ( err.xhr && err.xhr.status === 408 ) { | |
| return $.xhr( err.options ); | |
| } | |
| // Some other error, re-throw and we'll catch below | |
| throw( err ); | |
| }) | |
| .then( function() { | |
| console.log( "User created" ); | |
| }) | |
| .catch( function( err ) { | |
| // We could be specific with .options and .xhr if needed | |
| console.error( err.message ); | |
| }); | |
| // GET where the caller wants us to guess type based on response, | |
| // pretty much like $.ajax but with the type returned | |
| $.xhr( "/user/123/" ) | |
| .then( $.xhr.toContentType ) | |
| .then( function( response ) { | |
| if ( response.type !== "json" ) { | |
| throw( "I WANT JSON" ); | |
| } | |
| console.log( "Name: ", response.data.name ); | |
| }) | |
| .catch( function( err ) { | |
| console.error( err ); | |
| }); | |
| // ------------------- Helpers ------------------- | |
| // Helper to create error/success callback based on HTTP code and | |
| // convert types, similar to current jQuery $.ajax distinction. | |
| // N.B. I think this should be a plugin rather than built in | |
| jQuery.xhr.toSuccessError = function( successFn, errorFn ) { | |
| return function( err, xhr, options ) { | |
| // Call errorFn if err or xhr.status !== 2xx or conversion fails, | |
| // otherwise call sucessFn with converted data | |
| }; | |
| }; | |
| // Any $.xhr caller could also use xhr.response directly in XHR2 | |
| // as long as xhr.responseType was set before the call. | |
| // (So should we do that as part of options processing?) | |
| jQuery.xhr.toJSON = function( xhr ) { | |
| return jQuery.parseJSON( xhr.responseText ); | |
| }; | |
| jQuery.xhr.toDOM = function( xhr ) { | |
| return jQuery.parseHTML( xhr.responseText ); | |
| }; | |
| jQuery.xhr.toText = function( xhr ) { | |
| return xhr.responseText; | |
| }; | |
| jQuery.xhr.toScript = function( xhr ) { | |
| return jQuery.globalEval( xhr.responseText ); | |
| }; | |
| jQuery.xhr.toContentType( xhr ) { | |
| // Look at Content-Type of response to determine what to | |
| // return, similar to "intelligent guess" in $.ajax | |
| return { | |
| type: "json", | |
| data: { }, | |
| xhr: xhr | |
| }; | |
| }; | |
| jQuery.xhr.factory = function() { | |
| return new XMLHttpRequest(); | |
| }; | |
Hello I have some suggestions and equiries here :
1- I have seen that some javascript libraries can transform any thenable to a promise. Take for example : https://github.com/cujojs/when/blob/master/docs/api.md#when. I was thinking of a small thenable (Acting like an equivalent callback) version that can be coerced to a promise. There is some mechanism in every library, including W3C version of Promise : https://github.com/domenic/promises-unwrapping. At "compilation" step, any promise library can be plugged in, there is any dependance on any particular library.
2- Is there a way to have a factory mechanism to xhr ? So that, you can create a sandboxed version of the object and have a scoped set of default configurations. $.xhrFactory(defaultSettings).
3- How can we access the base XHR ? Thinking of it, it made me thinking why don't we have just a lightweight mechanism like ?
- $.xhr( XHR ).set({url:, type: }).request().then(successCallBack, errorCallBack);
or like this ? - var jqXHR = $.xhr({url: type});
jqXHR.get('url');
jqXHR.set({url: 'request/'});
jqXHR.request().then(function () { });
Simply, having xhr as a thin layer to the base XHR, that simplify its programming in a cross browser way. That's my personal opinion.
Gist updated ...