📄 xhr.js
字号:
// will receive one argument, the Deferred object that is related to the // canceller. // okHandler: // The first OK callback to be registered with Deferred. It has the opportunity // to transform the OK response. It will receive one argument -- the Deferred // object returned from this function. // errHandler: // The first error callback to be registered with Deferred. It has the opportunity // to do cleanup on an error. It will receive two arguments: error (the // Error object) and dfd, the Deferred object returned from this function. var ioArgs = {args: args, url: args.url}; //Get values from form if requestd. var formObject = null; if(args.form){ var form = _d.byId(args.form); //IE requires going through getAttributeNode instead of just getAttribute in some form cases, //so use it for all. See #2844 var actnNode = form.getAttributeNode("action"); ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null); formObject = _d.formToObject(form); } // set up the query params var miArgs = [{}]; if(formObject){ // potentially over-ride url-provided params w/ form values miArgs.push(formObject); } if(args.content){ // stuff in content over-rides what's set by form miArgs.push(args.content); } if(args.preventCache){ miArgs.push({"dojo.preventCache": new Date().valueOf()}); } ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs)); // .. and the real work of getting the deferred in order, etc. ioArgs.handleAs = args.handleAs || "text"; var d = new _d.Deferred(canceller); d.addCallbacks(okHandler, function(error){ return errHandler(error, d); }); //Support specifying load, error and handle callback functions from the args. //For those callbacks, the "this" object will be the args object. //The callbacks will get the deferred result value as the //first argument and the ioArgs object as the second argument. var ld = args.load; if(ld && _d.isFunction(ld)){ d.addCallback(function(value){ return ld.call(args, value, ioArgs); }); } var err = args.error; if(err && _d.isFunction(err)){ d.addErrback(function(value){ return err.call(args, value, ioArgs); }); } var handle = args.handle; if(handle && _d.isFunction(handle)){ d.addBoth(function(value){ return handle.call(args, value, ioArgs); }); } d.ioArgs = ioArgs; // FIXME: need to wire up the xhr object's abort method to something // analagous in the Deferred return d; } var _deferredCancel = function(/*Deferred*/dfd){ //summary: canceller function for dojo._ioSetArgs call. dfd.canceled = true; var xhr = dfd.ioArgs.xhr; var _at = typeof xhr.abort; if(_at == "function" || _at == "unknown"){ xhr.abort(); } var err = new Error("xhr cancelled"); err.dojoType = "cancel"; return err; } var _deferredOk = function(/*Deferred*/dfd){ //summary: okHandler function for dojo._ioSetArgs call. return _d._contentHandlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr); } var _deferError = function(/*Error*/error, /*Deferred*/dfd){ //summary: errHandler function for dojo._ioSetArgs call. // console.debug("xhr error in:", dfd.ioArgs.xhr); console.debug(error); return error; } var _makeXhrDeferred = function(/*dojo.__XhrArgs*/args){ //summary: makes the Deferred object for this xhr request. var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError); //Pass the args to _xhrObj, to allow xhr iframe proxy interceptions. dfd.ioArgs.xhr = _d._xhrObj(dfd.ioArgs.args); return dfd; } // avoid setting a timer per request. It degrades performance on IE // something fierece if we don't use unified loops. var _inFlightIntvl = null; var _inFlight = []; var _watchInFlight = function(){ //summary: // internal method that checks each inflight XMLHttpRequest to see // if it has completed or if the timeout situation applies. var now = (new Date()).getTime(); // make sure sync calls stay thread safe, if this callback is called // during a sync call and this results in another sync call before the // first sync call ends the browser hangs if(!_d._blockAsync){ // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating // note: the second clause is an assigment on purpose, lint may complain for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){ var dfd = tif.dfd; try{ if(!dfd || dfd.canceled || !tif.validCheck(dfd)){ _inFlight.splice(i--, 1); }else if(tif.ioCheck(dfd)){ _inFlight.splice(i--, 1); tif.resHandle(dfd); }else if(dfd.startTime){ //did we timeout? if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){ _inFlight.splice(i--, 1); var err = new Error("timeout exceeded"); err.dojoType = "timeout"; dfd.errback(err); //Cancel the request so the io module can do appropriate cleanup. dfd.cancel(); } } }catch(e){ // FIXME: make sure we errback! (fixed? remove console.debug?) console.debug(e); dfd.errback(new Error("_watchInFlightError!")); } } } if(!_inFlight.length){ clearInterval(_inFlightIntvl); _inFlightIntvl = null; return; } } dojo._ioCancelAll = function(){ //summary: Cancels all pending IO requests, regardless of IO type //(xhr, script, iframe). try{ _d.forEach(_inFlight, function(i){ i.dfd.cancel(); }); }catch(e){/*squelch*/} } //Automatically call cancel all io calls on unload //in IE for trac issue #2357. if(_d.isIE){ _d.addOnUnload(_d._ioCancelAll); } _d._ioWatch = function(/*Deferred*/dfd, /*Function*/validCheck, /*Function*/ioCheck, /*Function*/resHandle){ //summary: watches the io request represented by dfd to see if it completes. //dfd: // The Deferred object to watch. //validCheck: // Function used to check if the IO request is still valid. Gets the dfd // object as its only argument. //ioCheck: // Function used to check if basic IO call worked. Gets the dfd // object as its only argument. //resHandle: // Function used to process response. Gets the dfd // object as its only argument. if(dfd.ioArgs.args.timeout){ dfd.startTime = (new Date()).getTime(); } _inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle}); if(!_inFlightIntvl){ _inFlightIntvl = setInterval(_watchInFlight, 50); } _watchInFlight(); // handle sync requests } var _defaultContentType = "application/x-www-form-urlencoded"; var _validCheck = function(/*Deferred*/dfd){ return dfd.ioArgs.xhr.readyState; //boolean } var _ioCheck = function(/*Deferred*/dfd){ return 4 == dfd.ioArgs.xhr.readyState; //boolean } var _resHandle = function(/*Deferred*/dfd){ var xhr = dfd.ioArgs.xhr; if(_d._isDocumentOk(xhr)){ dfd.callback(dfd); }else{ var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status); err.status = xhr.status; err.responseText = xhr.responseText; dfd.errback(err); } } var _doIt = function(/*String*/type, /*Deferred*/dfd){ // IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open). // workaround for IE6's apply() "issues" var ioArgs = dfd.ioArgs; var args = ioArgs.args; var xhr = ioArgs.xhr; xhr.open(type, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined); if(args.headers){ for(var hdr in args.headers){ if(hdr.toLowerCase() === "content-type" && !args.contentType){ args.contentType = args.headers[hdr]; }else{ xhr.setRequestHeader(hdr, args.headers[hdr]); } } } // FIXME: is this appropriate for all content types? xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType); if(!args.headers || !args.headers["X-Requested-With"]){ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); } // FIXME: set other headers here! try{ xhr.send(ioArgs.query); }catch(e){ dfd.cancel(); } _d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle); xhr = null; return dfd; //Deferred } dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){ //summary: Adds query params discovered by the io deferred construction to the URL. //Only use this for operations which are fundamentally GET-type operations. if(ioArgs.query.length){ ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query; ioArgs.query = null; } } /*===== dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, { constructor: function(){ // summary: // In addition to the properties listed for the dojo._IoArgs type, // the following properties are allowed for dojo.xhr* methods. // handleAs: String? // Acceptable values are: text (default), json, json-comment-optional, // json-comment-filtered, javascript, xml // sync: Boolean? // false is default. Indicates whether the request should // be a synchronous (blocking) request. // headers: Object? // Additional HTTP headers to send in the request. this.handleAs = handleAs; this.sync = sync; this.headers = headers; } }); =====*/ dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){ // summary: // Sends an HTTP request with the given method. If the request has an // HTTP body, then pass true for hasBody. The method argument should be uppercase. // Also look at dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts // for those HTTP methods. There are also methods for "raw" PUT and POST methods // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively. var dfd = _makeXhrDeferred(args); if(!hasBody){ _d._ioAddQueryToUrl(dfd.ioArgs); } return _doIt(method, dfd); // dojo.Deferred } dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){ // summary: // Sends an HTTP GET request to the server. return _d.xhr("GET", args); //dojo.Deferred } dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){ //summary: // Sends an HTTP POST request to the server. return _d.xhr("POST", args, true); // dojo.Deferred } dojo.rawXhrPost = function(/*dojo.__XhrArgs*/ args){ // summary: // Sends an HTTP POST request to the server. In addtion to the properties // listed for the dojo.__XhrArgs type, the following property is allowed: // postData: // String. The raw data to send in the body of the POST request. var dfd = _makeXhrDeferred(args); dfd.ioArgs.query = args.postData; return _doIt("POST", dfd); // dojo.Deferred } dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){ // summary: // Sends an HTTP PUT request to the server. return _d.xhr("PUT", args, true); // dojo.Deferred } dojo.rawXhrPut = function(/*dojo.__XhrArgs*/ args){ // summary: // Sends an HTTP PUT request to the server. In addtion to the properties // listed for the dojo.__XhrArgs type, the following property is allowed: // putData: // String. The raw data to send in the body of the PUT request. var dfd = _makeXhrDeferred(args); var ioArgs = dfd.ioArgs; if(args.putData){ ioArgs.query = args.putData; args.putData = null; } return _doIt("PUT", dfd); // dojo.Deferred } dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){ // summary: // Sends an HTTP DELETE request to the server. return _d.xhr("DELETE", args); //dojo.Deferred } /* dojo.wrapForm = function(formNode){ //summary: // A replacement for FormBind, but not implemented yet. // FIXME: need to think harder about what extensions to this we might // want. What should we allow folks to do w/ this? What events to // set/send? throw new Error("dojo.wrapForm not yet implemented"); } */})();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -