新聞中心
在任何瀏覽器上方便地實(shí)現(xiàn)Ajax請(qǐng)求是每一個(gè)Ajax框架的初衷。Dojo在這方面無疑提供了非常豐富的支持。除了XMLHttpRequest之外,動(dòng)態(tài)script、iframe、RPC也應(yīng)有盡有,并且接口統(tǒng)一,使用方便,大多數(shù)情況下都只需要一句話就能達(dá)到目的,從而免除重復(fù)造輪子的麻煩。而且,Dojo一貫追求的概念完整性也在這里有所體現(xiàn),換句話說,在使用Dojo的Ajax工具的過程中不會(huì)感到任何的不自然,相反更容易有觸類旁通的感覺,因?yàn)锳PI的模式是統(tǒng)一的,而且這里涉及到的某些概念(如Deferred對(duì)象)也貫穿在整個(gè)Dojo之中。

鄆城ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!
Dojo的XHR函數(shù)
Dojo的XMLHttpRequest函數(shù)就叫dojo.xhr,除了把自己取名美元符號(hào)之外,這好像是最直接的辦法了。它定義在Dojo基本庫(kù)里,所以不需要額外的require就能使用。它可以實(shí)現(xiàn)任何同域內(nèi)的http請(qǐng)求。不過更常用的是dojo.xhrGet和dojo.xhrPost,它們只不過是對(duì)dojo.xhr函數(shù)的簡(jiǎn)單封裝;當(dāng)然根據(jù)REST風(fēng)格,還有dojo.xhrPut和dojo.xhrDelete。
這些函數(shù)的參數(shù)都很統(tǒng)一。除了dojo.xhr的第一個(gè)參數(shù)是http方法名之外,所有的dojo.xhr*系列函數(shù)都接受同一種散列式的參數(shù),其中包含請(qǐng)求的細(xì)節(jié),例如url、是否同步、要傳給服務(wù)器的內(nèi)容(可以是普通對(duì)象、表單、或者純文本)、超時(shí)設(shè)定、返回結(jié)果的類型(非常豐富且可擴(kuò)展)、以及請(qǐng)求成功和失敗時(shí)的回調(diào)。所有dojo.xhr*函數(shù)(實(shí)際上是所有IO函數(shù))返回值也都一樣,都是一個(gè)Deferred對(duì)象,顧名思義,它能讓一些事情“延遲”發(fā)生,從而讓API用起來更靈活。
下面的兩個(gè)例子可能會(huì)帶來一點(diǎn)直觀感受:
- dojo.xhrGet({
- url: "something.html",
- load: function(response, ioArgs){
- //用response干一些事
- console.log("xhr get success:", response);
- return response; //必須返回response
- },
- error: function(response, ioArgs){
- console.log("xhr get failed:", response);
- return response; //必須返回response
- }
- });
- //Deferred對(duì)象允許用同步調(diào)用的寫法寫異步調(diào)用
- var deferredResult = dojo.xhrPost({
- url: "something.html",
- form: formNode, //Dojo會(huì)自動(dòng)將form轉(zhuǎn)成object
- timeout: 3000, //Dojo會(huì)保證超時(shí)設(shè)定的有效性
- handleAs: "json" //得到的response將被認(rèn)為是JSON,并自動(dòng)轉(zhuǎn)為object
- });
- //當(dāng)響應(yīng)結(jié)果可用時(shí)再調(diào)用回調(diào)函數(shù)
- deferredResult.then(function(response){
- console.log("xhr get success:", response);
- return response; //必須返回response
- });
首先解釋一下timeout。除了IE8之外,目前大多數(shù)XMLHttpRequest對(duì)象都沒有內(nèi)置的timeout功能,因此必須用 setTimeout。當(dāng)同時(shí)存在大量請(qǐng)求時(shí),需要為每一個(gè)請(qǐng)求設(shè)置單獨(dú)的定時(shí)器,這在某些瀏覽器(主要是IE)會(huì)造成嚴(yán)重的性能問題。dojo的做法是只用一個(gè)單獨(dú)的setInterval,定時(shí)輪詢(間隔50ms)所有還未結(jié)束的請(qǐng)求的狀態(tài),這樣就高效地解決了一切遠(yuǎn)程請(qǐng)求(包括JSONP和 iframe)的超時(shí)問題。
值得一提的還有handleAs參數(shù),通過設(shè)置這個(gè)參數(shù),可以自動(dòng)識(shí)別服務(wù)器的響應(yīng)內(nèi)容格式并轉(zhuǎn)換成對(duì)象或文本等方便使用的形式。根據(jù)文檔,它接受如下值:text (默認(rèn)), json, json-comment-optional, json-comment-filtered, javascript, xml。
而且它還是可擴(kuò)展的。其實(shí)handleAs只是告訴xhr函數(shù)去調(diào)用哪個(gè)格式轉(zhuǎn)換插件,即dojo.contentHandlers對(duì)象里的一個(gè)方法。例如 dojo.contentHandlers.json就是處理JSON格式的插件。你可以方便地定制自己所需要的格式轉(zhuǎn)換插件,當(dāng)然,你也可修改現(xiàn)有插件的行為:
- dojo.contentHandlers.json = (function(old){
- return function(xhr){
- var json = old(xhr);
- if(json.someSignalFormServer){
- doSomthing(json);
- delete json.someSignalFormServer;
- }
- return json;
- }
- })(dojo.contentHandlers.json);//一個(gè)小技巧,利用傳參得到原方法
虛擬的參數(shù)類
這里特別提一下Dojo在API設(shè)計(jì)上的兩個(gè)特點(diǎn)。其一是虛擬的參數(shù)“類”概念:通過利用javascript對(duì)象可以靈活擴(kuò)展的特點(diǎn),強(qiáng)行規(guī)定一個(gè)散列參數(shù)屬于某個(gè)“類”。例如dojo.xhr*系列函數(shù)所接受的參數(shù)就稱為dojo.__XhrArgs。這個(gè)“類”并不存在于實(shí)際代碼中(不要試圖用 instanceof驗(yàn)證它),只停留在概念上,比抽象類還抽象,因此給它加上雙下劃線前綴(Dojo習(xí)慣為抽象類加單下劃線前綴)。這樣做看起來沒什么意思,但實(shí)際上簡(jiǎn)化了API,因?yàn)樗笰PI之間產(chǎn)生了聯(lián)系,更容易記憶也就更易于使用。這一點(diǎn)在對(duì)這種類做“繼承”時(shí)更明顯。例如 dojo.__XhrArgs繼承自dojo.__IoArgs,這是所有IO函數(shù)所必須支持的參數(shù)集合,同樣繼承自dojo.__IoArgs的還有 dojo.io.script.__ioArgs和dojo.io.iframe.__ioArgs,分別用于動(dòng)態(tài)腳本請(qǐng)求和iframe請(qǐng)求。子類只向父類添加少量的屬性,這樣繁多的參數(shù)就具有了樹形類結(jié)構(gòu)。原本散列式參數(shù)是用精確的參數(shù)名代替了固定的參數(shù)順序,在增加靈活性和可擴(kuò)展性的同時(shí),實(shí)際上增加了記憶量(畢竟參數(shù)名不能拼錯(cuò)),使得API都不像看起來那么好用,有了參數(shù)類的設(shè)計(jì)就緩解了這個(gè)問題。
這種參數(shù)類的做法在Dojo里隨處可見,讀源碼的話就會(huì)發(fā)現(xiàn)它們都是被正兒八經(jīng)地以正常代碼形式聲明在一種特殊注釋格式里的,像這樣:
- /*=====
- dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
- constructor: function(){
- //summary:
- //...
- //handleAs:
- //...
- //......
- }
- });
- =====*/
這種格式可以被jsDoc工具自動(dòng)提取成文檔,在文檔里這些虛擬出來的類就像真的類一樣五臟俱全了。
Deferred對(duì)象
另一個(gè)API設(shè)計(jì)特點(diǎn)就是Deferred對(duì)象的廣泛使用。Dojo里的Deferred是基于MochiKit實(shí)現(xiàn)稍加改進(jìn)而成的,而后者則是受到 python的事件驅(qū)動(dòng)網(wǎng)絡(luò)工具包Twisted里同名概念的啟發(fā)。概括來說的話,這個(gè)對(duì)象的作用就是將異步IO中回調(diào)函數(shù)的聲明位置與調(diào)用位置分離,這樣在一個(gè)異步IO最終完成的地方,開發(fā)人員可以簡(jiǎn)單地說“貨已經(jīng)到了,想用的可以來拿了”,而不用具體地指出到底該調(diào)用哪些回調(diào)函數(shù)。這樣做的好處是讓異步IO的寫法和同步IO一樣(對(duì)數(shù)據(jù)的處理總是在取數(shù)據(jù)函數(shù)的外面,而不是里面),從而簡(jiǎn)化異步編程。
具體做法是,異步函數(shù)總是同步地返回一個(gè)代理對(duì)象(這就是Deferred對(duì)象),可以將它看做你想要的數(shù)據(jù)的代表,它提供一些方法以添加回調(diào)函數(shù),當(dāng)數(shù)據(jù)可用時(shí),這些回調(diào)函數(shù)(可以由很多個(gè))便會(huì)按照添加順序依次執(zhí)行。如果在取數(shù)據(jù)過程中出現(xiàn)錯(cuò)誤,就會(huì)調(diào)用所提供的錯(cuò)誤處理函數(shù)(也可以有很多個(gè));如果想要取消這個(gè)異步請(qǐng)求,也可通過Deferred對(duì)象的cancel方法完成。
dojo.Deferred的核心方法如下:
- then(callback, errback); //添加回調(diào)函數(shù)
- callback(result); //表示異步調(diào)用成功完成,觸發(fā)回調(diào)函數(shù)
- errback(error); //表示異步調(diào)用中產(chǎn)生錯(cuò)誤,觸發(fā)錯(cuò)誤處理函數(shù)
- cancel(); //取消異步調(diào)用
Dojo還提供了一個(gè)when方法,使同步的值和異步的Deferred對(duì)象在使用時(shí)寫法一樣。例如:
- //某個(gè)工具函數(shù)的實(shí)現(xiàn)
- var obj = {
- getItem: function(){
- if(this.item){
- return this.item; //這里同步地返回?cái)?shù)據(jù)
- }else{
- return dojo.xhrGet({ //這里返回的是Deferred對(duì)象
- url: "toGetItem.html",
- load: dojo.hitch(this, function(response){
- this.item = response;
- return response;
- })
- });
- }
- }
- };
- //用戶代碼
- dojo.when(obj.getItem(), function(item){
- //無論同步異步,使用工具函數(shù)getItem的方式都一樣
- });
在函數(shù)閉包的幫助下,Deferred對(duì)象的創(chuàng)建和使用變得更為簡(jiǎn)單,你可以輕易寫出一個(gè)創(chuàng)建Deferred對(duì)象的函數(shù),以同步的寫法做異步的事。例如寫一個(gè)使用store獲取數(shù)據(jù)的函數(shù):
- var store = new dojo.data.QueryReadStore({...});
- function getData(start, count){
- var d = new dojo.Deferred(); //初始化一個(gè)Deferred對(duì)象
- store.fetch({
- start: start,
- count: count,
- onComplete: function(items){
- //直接取用上層閉包里的Deferred對(duì)象
- d.callback(items);
- }
- });
- return d; //把它當(dāng)做結(jié)果返回
- }
#p#
用dojo.io.script跨域
dojo.xhr* 只是XmlHttpRequest對(duì)象的封裝,由于同源策略限制,它不能發(fā)跨域請(qǐng)求,要跨域還是需要?jiǎng)討B(tài)創(chuàng)建


咨詢
建站咨詢