生活随笔
收集整理的這篇文章主要介紹了
jquery.ajax
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
這所有的最終都是通過jQuery.ajax()來完成的。 ??ajax?:?function(s)?{ ????????????s?=?jQuery.extend(true,?s,?jQuery.extend(true,?{},? ??jQuery.ajaxSettings,????s));?????????① ??????var?jsonp,?jsre?=?/=\?(&|$)/g,?status,?data, ???type?=?s.type??.toUpperCase(); ????if?(s.data?&&?s.processData?&&?typeof?s.data?!=?"string") ??????????s.data?=?jQuery.param(s.data); ??????if?(s.dataType?==?"jsonp")?{???????????????????????????????② ??if?(type?==?"GET")?{??????????if?(!s.url.match(jsre)) ??????????????s.url?+=?(s.url.match(/\?/)???"&"?:?"?") ??????????????????????????????+?(s.jsonp?||?"callback")?+?"=?"; ??????????????}???else?if?(!s.data?||?!s.data.match(jsre)) ??????????s.data?=?(s.data???s.data?+?"&"?:?"")?+?(s.jsonp||"callback")+?"=?"; ??s.dataType?=?"json"; ??}??????? ????if?(s.dataType?==?"json"?? ??????????????&&?(s.data?&&?s.data.match(jsre)?||?s.url.match(jsre)))?{③ ???????jsonp?=?"jsonp"?+?jsc++; ??/?/為請求字符集串的callback=加上生成回調(diào)函數(shù)名 ??????if?(s.data)s.data?=?(s.data?+?"").replace(jsre,?"="?+?jsonp?+?"$1"); ??????s.url?=?s.url.replace(jsre,?"="?+?jsonp?+?"$1"); ??????????????????????????????????s.dataType?=?"script"; ??????????????window[jsonp]?=?function(tmp)?{ ??????????data?=?tmp;success();complete(); ???????????????window[jsonp]?=?undefined; ??????????try?{???delete?window[jsonp]; ??????????????}?catch?(e)?{???} ??????????if?(head)???head.removeChild(script); ??????????}; ??????} ????if?(s.dataType?==?"script"?&&?s.cache?==?null)??s.cache?=?false; ????if?(s.cache?===?false?&&?type?==?"GET")?{ ??????var?ts?=?now(); ??????var?ret?=?s.url.replace(/(\?|&)_=.*?(&|$)/,?"$1_="?+?ts?+?"$2"); ????????????s.url?=?ret+?((ret?==?s.url)???(s.url.match(/\?/)???"&"?:?"?")?+?"_="??????????????????????????+?ts?:?""); ??????} ????if?(s.data?&&?type?==?"GET")?{ ??????????s.url?+=?(s.url.match(/\?/)???"&"?:?"?")?+?s.data; ????????????????????s.data?=?null; ??????????} ????if?(s.global?&&?!jQuery.active++)?jQuery.event.trigger("ajaxStart");④ ????var?parts?=?/^(\w+:)?\/\/([^\/?#]+)/.exec(s.url); ??????if?(s.dataType?==?"script"??&&?type?==?"GET"&&?parts????&&?(parts[1]?&&? ??parts[1]?!=?location.protocol?||?parts[2]?!=?location.host))?{⑤ ????????????????????var?head?=?document.getElementsByTagName("head")[0]; ??????????var?script?=?document.createElement("script"); ??????????script.src?=?s.url; ??????????if?(s.scriptCharset)????script.charset?=?s.scriptCharset; ?????????????????????????????if?(!jsonp)?{ ??????????????var?done?=?false; ????????????????????????????script.onload?=?script.onreadystatechange?=?function()?{ ??????????????if?(!done&&?(!this.readyState?||?this.readyState?==?"loaded"? ??||?this.readyState?==?"complete"))?{ ??????????????????????done?=?true;????success(); ??????????????????????complete();head.removeChild(script); ??????????????????} ??????????}; ??????} ??????head.appendChild(script); ????????return?undefined; ??} ??var?requestDone?=?false; ????var?xhr?=?window.ActiveXObject???????????????????????????????⑥ ????????????new?ActiveXObject("Microsoft.XMLHTTP"):?new?XMLHttpRequest(); ????if?(s.username)xhr.open(type,?s.url,?s.async,?s.username,?s.password); ??else????xhr.open(type,?s.url,?s.async); ????try?{??????if?(s.data) ??????????xhr.setRequestHeader("Content-Type",?s.contentType); ????????????????if?(s.ifModified) ??????????xhr.setRequestHeader("If-Modified-Since", ??????????????jQuery.lastModified[s.url]||?"Thu,?01?Jan?1970?00:00:00?GMT"); ????????xhr.setRequestHeader("X-Requested-With",?"XMLHttpRequest"); ????????xhr.setRequestHeader("Accept",?s.dataType?&&?s.accepts[s.dataType] ????????????????s.accepts[s.dataType]?+?",?*/*":?s.accepts._default); ??}?catch?(e)?{} ????if?(s.beforeSend?&&?s.beforeSend(xhr,?s)?===?false)?{?????????⑧ ????????????s.global?&&?jQuery.active--; ??????xhr.abort(); ??????return?false; ??} ??????if?(s.global)???jQuery.event.trigger("ajaxSend",?[xhr,?s]); ????var?onreadystatechange?=?function(isTimeout)?{???????????⑨ ????if?(!requestDone?&&?xhr&&?(xhr.readyState?==?4?||isTimeout?==?"timeout"))?{?requestDone?=?true; ?????????????????????if?(ival)?{clearInterval(ival);?????ival?=?null;????} ????????????status?=?isTimeout?==?"timeout"???"timeout"?:?!jQuery ??????????ttpSuccess(xhr)???"error"?:?s.ifModified&&?jQuery. ??httpNotModified(xhr,?s.url)???"notmodified":?"success"; ????????????????if?(status?==?"success")?{?????????????????? ??????????try?{???data?=?jQuery.httpData(xhr,?s.dataType,?s); ???????????????}?catch?(e)?{??status?=?"parsererror";?} ??????} ????????if?(status?==?"success")?{ ??????????var?modRes; ????????????try?{modRes?=?xhr.getResponseHeader("Last-Modified"); ??????????????}?catch?(e)?{????????????????????????if?(s.ifModified?&&?modRes)jQuery.lastModified[s.url]?=?modRes; ???????????????????if?(!jsonp)?success(); ??????}?else????????jQuery.handleError(s,?xhr,?status); ????????complete(); ??if?(s.async)????xhr?=?null;???} ??}; ??if?(s.async)?{ ??????var?ival?=?setInterval(onreadystatechange,?13); ????????if?(s.timeout?>?0) ??????????setTimeout(function()?{????????????????? ??????????????if?(xhr)?{??xhr.abort(); ??????????????????if?(!requestDone)???onreadystatechange("timeout");??} ??????????},?s.timeout); ??????} ????try?{xhr.send(s.data);?catch(e){jQuery.handleError(s,xhr,null,e);}?⑩ ????if?(!s.async)???onreadystatechange(); ??function?success()?{ ????????????if?(s.success)??s.success(data,?status); ????????????if?(s.global)???jQuery.event.trigger("ajaxSuccess",?[xhr,?s]); ??????} ??function?complete()?{ ????????????if?(s.complete)?s.complete(xhr,?status); ????????????if?(s.global)???jQuery.event.trigger("ajaxComplete",?[xhr,?s]); ????????????if?(s.global?&&?!--jQuery.active)jQuery.event.trigger("ajaxStop"); ??????} ????return?xhr; ??}, ??Jquery.ajax是大包大攬的非常復(fù)雜的一個方法。它并沒有像其它的lib一樣,把每個小部分都分開來。它是整個都整在一個函數(shù)中。看起來很多,實際上上也沒有脫離前面所說的ajax的請求的五步。它的很大一部分代碼在處理跨域請求的處理上。下面就分別就ajax的代碼進行分析。 ??ajaxSettings ??在①處通過繼承的方式把傳入?yún)?shù)s和默認(rèn)的jQuery.ajaxSettings都clone到s變量中。S的同名屬性會覆蓋jQuery.ajaxSettings的同名屬性。這里兩次繼承s,以便在測試中能檢測。 ????????ajaxSettings?:?{ ??????????url?:?location.href,??????????global?:?true,??????????type?:?"GET", ??????????timeout?:?0, ??????????contentType?:?"application/x-www-form-urlencoded",?? ???????processData?:?true, ??????????async?:?true, ??????????data?:?null, ??????????username?:?null, ??????????password?:?null, ??????????accepts?:?{ ??????????????xml?:?"application/xml,?text/xml", ??????????????html?:?"text/html", ??????????????script?:?"text/javascript,?application/javascript", ??????????????json?:?"application/json,?text/javascript", ??????????????text?:?"text/plain", ??????????????_default?:?"*/*"??????????} ??這是默認(rèn)的ajax的設(shè)定,我們要在參數(shù)s設(shè)定同名的屬性來覆蓋這些屬性。但是我們不能覆蓋accepts。這個會在后面的代碼用到。我們可以通過設(shè)定s.dataType等于accepts中的某一個屬性key指定請求的data類型,如xml,html,script,json,text。dataType還支持默認(rèn)的_default和跨域的jsonp。不過其最終會解析成script。 ??scriptTag ??②~⑥是處理跨域請求的部分。對于dataType為jsonp的類型,給其請求的字符串(可能是s.data)加上callback=callbackfn的key/value串,然后在window下注冊一個callbackfn的函數(shù)。這個函數(shù)的形式如callbackfn(data){?data?=?tmp;success();complete();}。它代理了通過ajax(s)的傳入s參數(shù)中success();complete()的功能。它就是調(diào)用這個函數(shù),實際上是調(diào)用success();complete()的函數(shù)。 ??那么怎么調(diào)用呢?ajax不支持跨域。在⑤處,我們可以看到這里是采用scriptTag的方式來完成。先在頁面的<head>中添加一個<script?src=url?/>的標(biāo)簽。因為在<head>中。瀏覽器會自動載入并運行請求返回的script。如果是jsonp的形式,服務(wù)器端還要動態(tài)生成的content-type為script的代碼:callbackfn(data);只有這樣才會調(diào)用在window中注冊的函數(shù)callbackfn。同時傳入所需要的參數(shù)。 ??如dataType?==?"script"形式的跨域,那只能是通過script.onload?或?script.onreadystatechange事件來觸發(fā)回調(diào)。這里我們可以通過服務(wù)器返回的script代碼:var?data=xxx。來傳遞參數(shù)給s.success();s.complete()。Jquery這里采用是全局變量data來進行操作的。 ??Ajax?Event ??④是采用了jQuery.event.trigger("ajaxStart");來觸發(fā)全局的ajaxStart事件。這也是說只要注冊了這個事件的元素,在任何的ajax的請求時ajaxStart都會執(zhí)行元素注冊的事件處理函數(shù)。這和Ext的事件有點相似。但是它不是全局的。 ??jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),?function(i,?o)?{ ??????jQuery.fn[o]?=?function(f)?{??????????return?this.bind(o,?f); ??????}; ??上面的代碼是為jquery對象注冊了ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend這幾種ajax的事件方法,在jquery.ajax中不同的時刻都會觸發(fā)這些事件。當(dāng)然我們也可以采用s.global=false來設(shè)定不觸發(fā)這些事件。 ??因為這是全局的,個人認(rèn)為其設(shè)計的目的就是為了在這些時候能以某種形式來告訴用戶ajax的進行的狀態(tài)。如在ajaxstart的時候,我們可能通過一個topest的div層(加上遮罩的效果)的元素注冊一個ajaxstart事件的處理方法。該方法就是顯示這個層和顯示“你的數(shù)據(jù)正在提交。。。”這個的提示。這是這6種事件的最佳用法了。 ??如果進行私有處理,那么要在事件的處理函數(shù)中進行判斷。因為每個事件處理函數(shù)的第二參數(shù)是jquery.ajax(s)的s參數(shù)。我們可以在這個參數(shù)中做私有的標(biāo)識,如eventType:xxx。每類不同的請求有不同的eventType值。在事件處理函數(shù)再根據(jù)這個eventType==xxx進行判斷,從而進行私有的處理。如果有大量的這樣的私有處理也是會影響ajax的效率的。 ??setRequestHeader ??⑥處是創(chuàng)建一個xhr對象并通過open來創(chuàng)建一個連接(socket)。 ??⑦處是設(shè)定請求的頭部(setRequestHeader)。如果data的存在的話,那就得設(shè)定Content-Type,便于服務(wù)器按一定的規(guī)則來解碼。可以看出post的方式通過data傳遞數(shù)據(jù)要安全一點。 ??那么服務(wù)器如果區(qū)別這個請求是ajax呢?因為同步和異步ajax的請求的頭文件是一樣的。我們?nèi)绻ㄟ^X-Requested-With"="XMLHttpRequest”來標(biāo)識這個請求是ajax的請求。如果服務(wù)器硬是要區(qū)分的話,就可以通過獲取該頭部來判斷。 ??在頭部的定義中,還可能通過Accept來指定接受的數(shù)據(jù)的類型,如application/xml,?text/xml",?"text/html",?"text/javascript,?等等。 ??頭部還有一個If-Modified-Since的屬性用來提高效率的。它和”Last-Modified配合起來使用。在瀏覽器第一次請求某一個URL時,服務(wù)器端的返回狀態(tài)會是200,內(nèi)容是你請求的資源,同時有一個Last-Modified的屬性標(biāo)記此文件在服務(wù)期端最后被修改的時間,格式類似這樣:Last-Modified:?Fri,?12?May?2006?18:53:33?GMT? ??客戶端第二次請求此URL時,根據(jù)?HTTP?協(xié)議的規(guī)定,瀏覽器會向服務(wù)器傳送?If-Modified-Since?報頭,詢問該時間之后文件是否有被修改過:??If-Modified-Since:?Fri,?12?May?2006?18:53:33?GMT????如果服務(wù)器端的資源沒有變化,則自動返回?HTTP?304?(Not?Changed.)狀態(tài)碼,內(nèi)容為空,這樣就節(jié)省了傳輸數(shù)據(jù)量。 ??當(dāng)服務(wù)器端代碼發(fā)生改變或者重啟服務(wù)器時,則重新發(fā)出資源,返回和第一次請求時類似。從而保證不向客戶端重復(fù)發(fā)出資源,也保證當(dāng)服務(wù)器有變化時,客戶端能夠得到最新的資源。 ??攔截處理 ??⑧處是一個send之前的攔截處理,可以通過s.?beforeSend(xhr,?s)函數(shù)的形式傳入攔截函數(shù)。保證在發(fā)送之前確保滿足某些條件。在取得返回數(shù)據(jù)的時候,也可以通過s.dataFilter(data,?type);形式來攔截處理data。不過這里主要的作用對data進一步的篩選。 ??onreadystatechange ??⑨處是onreadystatechange的回調(diào)處理。這里采用是poll的形式進行處理。它把返回的狀態(tài)分成status:tiemout-->error-->notmodified-->success—>parsererror這幾種。如果status?==?"success"那么分析這些數(shù)據(jù)之后再進行l(wèi)ast-modified相關(guān)的處理。為了不取回沒有修改過數(shù)據(jù)。 ??分析數(shù)據(jù)的代碼如下: ????????httpData?:?function(xhr,?type,?s)?{ ??????????var?ct?=?xhr.getResponseHeader("content-type"),? ????????????xml?=?type?==?"xml"???||?!type?&&?ct?&&?ct.indexOf("xml")?>=?0,? ?????????????data?=?xml??xhr.responseXML??:?xhr.responseText; ??????????if?(xml?&&?data.documentElement.tagName?==?"parsererror") ??????????????throw?"parsererror"; ????????????????????if?(s?&&?s.dataFilter) ??????????????data?=?s.dataFilter(data,?type); ????????????????????????????if?(type?==?"script")???jQuery.globalEval(data); ????????????????????if?(type?==?"json")?????data?=?eval("("?+?data?+?")"); ??????????return?data; ??????}, ??如果返回的content-type是xml,html,text等都返回。對script執(zhí)行jQuery.globalEval來執(zhí)行它。對于Json類型,通過eval來生成返回的json對象。 ????globalEval?:?function(data)?{ ??????data?=?jQuery.trim(data); ??????????if?(data)?{ ????????????var?head?=?document.getElementsByTagName("head")[0] ??????????????????????????||?document.documentElement, ??????????script?=?document.createElement("script"); ??????script.type?=?"text/javascript"; ??????if?(jQuery.browser.msie)????script.text?=?data; ??????else????script.appendChild(document.createTextNode(data)); ????????????????????????head.insertBefore(script,?head.firstChild); ??????????head.removeChild(script); ??????????????}???????}, ????????????????????
總結(jié)
以上是生活随笔為你收集整理的jquery.ajax的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。