本文介紹了 Dojo 中三種瀏覽器與服務器交互的方式,這三種方式各有優缺點,可是在使用方式卻出奇的一致; xhr 框架的函數,dojo.io.iframe、dojo.io.script 對象的函數使用的 JSON 對象參數也極其類似,並且淺顯易懂。 Dojo 設計者的這一良好設計極大的減輕了開發人員的學習負擔,做爲框架開發人員應該瞭解這一理念。表 2 對這三種方式從三個方面進行了比較。javascript
支持的 HTTP 請求類型 | 指望的輸出 | 跨域 | |||
XHR | Get, post, delete, put | text, json, xml, javascript … | N | N | |
iframe | Get, post | html | N | N | |
script | Get | javascript | Y | Y |
在傳統的以頁面爲單位的瀏覽器和服務器交互模式中,每一次服務器請求都會致使整個頁面的從新加載,即便須要更新的僅僅是頁面的一小部分(好比顯示一個登陸錯誤信息)。 Ajax 技術的出現給頁面帶來了一些變化,其中最直觀的莫過於站點的頁面上出現愈來愈多的「 loading …」,「正在加載中……」等提示信息,有些忽如一晚上春風來,loading 加載到處開的意思。「 loading …」或者「正在加載中……」表示瀏覽器正在與服務器之間進行交互,交互完成以後,將對頁面進行局部刷新,這種交互模式雖然簡單卻極大的提升了 Web 應用的用戶體驗。實現這種模式的核心就是 XmlHttpRequest(後文簡稱 XHR)對象。php
XHR 對象促使愈來愈多「單一頁面」的 Web 應用的誕生。使用 XHR 對象能夠發送異步 HTTP 請求。由於是異步,在瀏覽器和服務器交互的過程當中,仍然能夠操做頁面。當頁面中有多個進行異步調用的 XHR 對象時,事情有了質的變化,每個 XHR 對象均可以獨立於服務器進行通訊,瀏覽器中的頁面彷彿是一個多線程的應用程序。這種多線程異步調用的特性給 Web 應用的開發帶來了很大的影響,愈來愈多像 Google Mail 這種「單一頁面」的應用涌現出來,並且大受歡迎。之因此能作到「單一頁面」是由於有不少的 XHR 對象默默地在背後服務,咱們能夠經過啓用 firebug 來查看每次在 Google Mail 頁面上的操做「生產」了多少個 XHR 對象。css
使用 XHR 對象的另外一個好處是能夠減小服務器返回的數據量,進而提高系統的性能。在原有的 B/S 交互模式中,服務器返回的是粗粒度的 HTML 頁面;使用 XHR 對象以後,服務器返回的是細粒度的數據,如 HTML,JSON,XML 等,請注意這裏返回的是數據而不是頁面,也就是說只返回須要更新的內容,而不返回已經在頁面上顯示的其餘內容,因此每次從服務器返回的數據量比原來要少。採用 AJAX 技術的 Web 應用在初次加載時花費的時間比較長,可是加載完成以後,其性能比原來的 Web 應用要好不少。html
這裏介紹了一些 XmlHttpRequest 對象給 Web 開發帶來的變化,這些變化是 Ajax 技術可以流行的重要緣由,認識這些變化能夠幫助開發人員設計、開發高效的 Web 應用。本文並不打算介紹 XmlHttpRequest 的屬性、方法,不少文章在這方面已經作得很好。前端
XmlHttpRequest 對象是 Dojo 中的 XHR 框架的基礎,目前主流瀏覽器都已經支持此對象,可是不一樣瀏覽器上實現方式卻不同,IE五、IE6 採用 ActiveX 對象的方式,Firefox 和 Safari 都實現爲一個內部對象,因此建立 XHR 對象以前須要先測試瀏覽器的類型,清單 1 展現了最簡單的建立 XHR 對象的代碼。jquery
1 function createXHR(){ 2 if (window.XMLHttpRequest) { // Non IE 3 return new XMLHttpRequest(); 4 } 5 else if (window.ActiveXObject) { // IE 6 return new ActiveXObject("Microsoft.XMLHTTP"); 7 } 8 }
或許是認識到 XHR 對象的重要性,微軟在 IE7 中已經把它實現爲一個窗口對象的屬性。可是判斷瀏覽器類型的代碼依然不能消除,由於 IE5, IE6 仍然有大量的使用者。git
XHR 對象建立方式不一致是 Dojo 的 XHR 框架誕生的一個緣由,更重要的緣由是原始 XHR 對象還不夠強大,有些方面不能知足開發的須要:首先 XHR 對象支持的返回類型有限,原始 XHR 對象只有 responseText 和 responseXML 兩個屬性表明返回的數據,重要的數據交換格式 JSON 就不被支持;其次不能設置 HTTP Request 的超時時間,設置超時時間可讓客戶端腳本控制請求存在的時間,而不是被動的等待服務器端的返回。github
基於這些問題,Dojo 組織提供了一組函數來支持各類 HTTP 請求,包括 xhrGet,rawXhrPost,xhrPut,rawXhrPut,xhrPut,xhrDelete,這幾個函數與 HTTP 協議中的四種請求是一一對應的,HTTP 四種請求是:Get(讀取),Post(更新),Put(建立),Delete(刪除)。 Dojo 組織的發起者 Alex Russell 把這些跟 XHR 對象相關的函數放在一塊兒稱爲 XHR 框架。下面咱們來看看 Dojo 是如何建立 XHR 對象的。清單 2 是 Dojo 1.1 中建立 XHR 對象的代碼片斷。web
d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; d._xhrObj= function(){ var http = null; var last_e = null; if(!dojo.isIE || !djConfig.ieForceActiveXXhr){ try{ http = new XMLHttpRequest(); }catch(e){} } if(!http){ for(var i=0; i<3; ++i){ var progid = dojo._XMLHTTP_PROGIDS[i]; try{ http = new ActiveXObject(progid); }catch(e){ last_e = e; } if(http){ dojo._XMLHTTP_PROGIDS = [progid]; break; } } } if(!http){ throw new Error("XMLHTTP not available: "+last_e); } return http; // XMLHTTPRequest instance }
_xhrObj 是 Dojo 建立的 XHR 對象。與清單 1 相比,是否是顯得有點「冗長」?其實否則,雖然多了不少 try-catch 語句,但這些 try-catch 塊保證了即便建立 XHR 對象出錯時,瀏覽器依然不會崩潰,加強了代碼的健壯性;此外,代碼對 IE 瀏覽器的「照顧」周到之至,三個 XHR 對象可能存在的命名空間('Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0')都作了判斷,只有這樣才能保證 XHR 對象在各個不一樣的瀏覽器能順利「誕生」。從這段代碼也能夠看出要編寫健壯、高效的代碼,開發人員必須具備系統性的思惟,並能合理使用錯誤處理機制。下面將對 XHR 框架中的每一個方法進行介紹。
xhrGet 是 XHR 框架中最重要的函數,使用頻率也最高。使用它便可以請求服務器上的靜態文本資源如 txt、xml 等,也能夠獲取動態頁面 php、jsp、asp 等,只要從服務器返回的是字符數據流便可。首先看一個簡單的例子。
function helloWorld(){ dojo.xhrGet({ url: "helloworld.txt" , //請求連接,不能跨域 handleAs: "txt", //返回格式,支持JSON load: function(response, ioArgs){alert(response);}, //回調函數 error: function(error, ioArgs){alert(error.message);} //錯誤處理 }); }
dojo.xhrGet 的參數是一個 JSON 對象,JSON 對象由不少的屬性 / 值對組成,其中的值能夠是任意類型的數據: 整形、字符串、函數……甚至是 JSON 對象,這一點使得 JSON 對象的數據描述能力能夠與 XML 匹敵,並且 JSON 對象可使用「 . 」操做符來直接訪問它的屬性,沒有任何解析的開銷,很是方便。在 Javascript 領域,JSON 大有超越 XML 成爲事實上的數據交換標準的趨勢。使用 JSON 對象做爲函數參數的情形在 Javascript 中很是廣泛,能夠當作 Javascript 開發中的一個模式,開發人員應該熟悉它。再回到做爲 xhrGet 參數的 JSON 對象,在清單 3 的例子中的,這一對象有四個屬性:
load, error 所指向的值便可以像清單 3 中所示的那樣是無名函數,也能夠是一個已經定義過的函數名,清單 3 的例子能夠修改以下:
1 function display(response, ioArgs) 2 { 3 alert(response); 4 } 5 function helloWorld2(){ 6 dojo.xhrGet({ 7 url: "helloworld.txt" , 8 handleAs: "txt", 9 load:display, //函數名稱 10 error:display}); 11 }
使用這一方法能夠提升代碼的複用率,尤爲在有多個 xhrGet 對象須要使用相同的 load 回調函數時。
無論 load 的回調函數是無名函數仍是預約義的有名函數,它都包含兩個參數:response 和 ioArgs(注意:這兩個參數的名稱能夠任意取,這裏只是使用了兩個經常使用的名稱。實際上,在 Javascript 中,函數是由函數名惟一聲明的,函數參數能夠不出如今函數的聲明中,在函數體內可使用 arguments 引用函數的實際參數)。
前面介紹了 xhrGet 函數以及與它關聯的回調函數,xhrGet 中的 handleAs 的設置決定了如何對服務器返回的數據進行預處理,表 1 詳細介紹了不一樣的 handleAs 表明的不一樣的預處理方式(即返回結果的格式)。
handleAs | 預處理方式 |
text | 默認值,不對返回的數據作任何處理 |
xml | 返回 XHR 對象的 responseXML |
javascript | 使用 dojo.eval 處理返回的數據,返回處理結果 |
json | 使用 dojo.fromJSon 來處理返回的數據,返回生成的 Json 對象 |
json-comment-optional | 若是有數據包含在註釋符中,則只使用 dojo.fromJSon 處理這部分數據,若是沒有數據包含在註釋符中,則使用 dojo.fromJSon 處理所有數據。 |
json-comment-filtered | 數據應該包含在 /* … */ 中,返回使用 dojo.fromJSon 生成的 Json 對象,若是數據不是包含在註釋符中則不處理。 |
把文本字符串轉換爲 JSON 對象
function jsonDemo() { response = ( "[{ name: 'Joe', age: '30', gender: 'M'}, { name: 'Chandler', age: '32', gender: 'M'}, { name: 'Rose', age: '31', gender: 'M'}]" ); json = eval(response); document.write(json[0].name + "," + json[1].age + "," + json[2].gender); }
表單的提交在 Web 應用中必不可少,之前 javascript 應用最廣的地方是作表單的驗證,今天咱們知道 javascript 能作的比這遠遠要多。使用 xhrGet 提交表單與請求資源相似,只須要在 xhrGet 的參數對象中增長一個屬性,關聯須要提交的 form 。使用 xhrGet 異步提交 form 意義重大,在傳統的 B/S 交互模式中,提交 form 則意味着頁面的跳轉,但不少狀況下頁面不用跳轉,好比用戶登陸時,用戶名或密碼錯誤,這時不跳轉頁面而是直接給出錯誤提示信息用戶體驗明顯要好得多,清單 6 是使用 xhrGet 提交表單的例子。
1 <html> 2 <body> 3 <script src="../dojo/dojo.js" 4 djConfig="parseOnLoad: true"></script> //表示肯定在頁面加載完成之後執行解析功能,但解析功能模塊的引入要靠 dojo.require("dojo.parser") 來實現 5 <script> 6 function handler(response) 7 { document.write(response); } 8 9 function submitForm(){ 10 dojo.xhrGet({ 11 form: "loginForm" , //要提交的表單id 12 handleAs: "text" , 13 handle: handler, //回調函數 14 content: { pwd: "modified" }, //能夠改變提交內容 15 sync: false //是否異步提交 16 }); 17 return false; 18 } 19 </script> 20 <form id="loginForm" onsubmit="return submitForm();" action="data.php"> //action表示表單提交的頁面 21 <input type="textfield" name="id" /> 22 <input type="password" name="pwd" /> 23 <input type="submit" name="sub" value="submit" /> 24 </form> 25 </body> 26 </html>
在這個例子中咱們看到 xhrGet 的一些新的參數。這些參數不是僅針對提交表單的,請求資源時也可使用。之因此在這裏介紹,是爲了達到按部就班學習的目的。例子中的 data.php 是服務器端的程序,比較簡單,只包含一行代碼 echo $_POST[「pwd」],用來輸出表單中的密碼字段。
須要注意的是:雖然表單提交的默認方法是 POST,但當使用 xhrGet 提交時,表單提交方式就自動改成 GET,全部表單的數據都會變成查詢字符串出如今 URL 中。因此在服務器端只能從查詢字符串中取得這些提交的信息。在 jsp 中是:request.getParameter(「PWD」),而在 PHP 中可使用 $_GET[「PWD」] 在服務器端獲取表單字段。
除了 xhrGet,Dojo 的 XHR 框架還包含 xhrPost,rawXhrPost,xhrPut,rawXhrPut,xhrDelete 。這幾個函數與 xhrGet 相似,使用方法和參數均可以參考 xhrGet 。區別在於他們的 HTTP 請求類型,xhrPost 發送的是 Post 請求,xhrPut 發送的是 Put 請求,xhrDelete 發生的是 Delete 請求。
xhrPost 通常用來發送表單數據,固然 xhrGet 也能夠作到,區別是 xhrPost 把表單數據封裝在 HTTP 請求的 Body 部分。在服務器端只能使用取 POST 信息的方法獲取這些表單數據,假設咱們要取清單 6 中的表單的 PWD 密碼框中的數據,在 JSP 中能夠是 request.getParameter(「PWD」),在 PHP 中能夠是 $_POST[「PWD」] 。
若是使用 xhrDelete 去刪除服務器上的資源,好比某一文件,由於它表示刪除服務器上的某一資源,而普通用戶是沒有權限刪除服務器上資源的權限的。因此使用 xhrDelete 方法時,通常回返回 405 錯誤(圖 1 是使用 javascript alert 顯示的錯誤信息),表示「對於請求所標識的資源,不容許使用請求行爲中所指定的方法」。
Dojo 提供這些方法的目的固然不是爲了方便開發人員增長 / 刪除 / 修改服務器上的物理資源,而是爲了支持 REST 架構風格。 REST 架構風格強調使用標準 HTTP 方法,即前文提到的 Get,Post,Put,Delete 來請求、操做 web 資源,注意不是物理資源。舉個例子,在 REST 架構中,新建訂單,應該使用 Put 方法,而刪除訂單應該使用 Delete 方法,而不像在之前的 Web 應用架構中,開發人員經過額外的參數來肯定操做的類型。 Dojo 提供這些方法對 REST 架構風格是很好的支持。
除了 XHR 框架,Dojo Core 還提供了一個 io 包,Dojo 的官方說明把他們描述成「高級傳輸層(advanced ajax transport layer)」,由兩個對象組成,dojo.io.iframe 和 dojo.io.script 。 使用 dojo.io.iframe 一樣能夠跟服務器交互,可是它採用了與 XHR 對象不一樣的實現思路。清單 7 是一個使用 iframe 方式提交表單的例子。
<html><body> <script src="../dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script> <script> dojo.require("dojo.io.iframe" ); function iframeTest(){ dojo.io.iframe.send({ form: dojo.byId('testForm') , url: "data.php" , method: "post" , handleAs: "html" , load: function(response, ioArgs) { alert(response); } }); } </script> <form id="testForm" method="post" > Name:<input type="text" name="name" size="40" /><br /> Sex:<input type="radio" name="sex" value="m" > Male<input type="radio" name="sex" value="f"> Female<br /> <input type="button" name="sub" value="submit" onclick="iframeTest()" /> </form> </body></html>
從這個例子中能夠看出,dojo.io.iframe 的使用方式、參數與 xhrGet 很是類似。其中,from,url,handleAs,load 等在 xhrGet 中也存在,惟一不一樣的是 method,method 表示 dojo.io.iframe 將以何種 HTTP Method 來發送請求。另外須要注意的一點是 handleAs 參數,dojo.io.iframe 通常使用 html,由於在 iframe 中存的實際上是另外一個 HTML 頁面。若是 handleAs 設置爲其餘值,像 json,text 等,則在服務器端須使用 <textarea></textarea> 把要返回的數據包裝起來,好比 hellow, world 要被包裝成 <textarea>hello,world</textarea>,因此最後存在 iframe 中的是一個文本域(textarea),這個文本域包含了從服務器端返回的數據。這麼作的緣由很簡單,就是爲了保持從服務器返回的數據「一成不變」,由於任何字符數據均可以「安全的」放在 HTML 頁面的文本域中。想像一下,咱們是否是能夠在文本域中輸入各類字符! dojo.io.iframe 會對 textarea 包裝的數據進行處理:首先把 textarea 標籤去掉,而後把數據轉換爲 handleAs 指定的類型傳遞給 handle 中設置的回調函數。
dojo.io.iframe 是如何工做的呢?除了 XHR 對象以外還有什麼方法能夠實現表單的異步提交?其實這一切都很簡單,dojo.io.iframe 首先會建立一個隱藏的 iframe 並插入到父頁面的最後,而後設置此 iframe 的 src 屬性爲dojo-module-path/resources/blank.html(dojo-module-path 指 dojo 包所在的目錄),iframe 頁面的 onload 事件的處理函數被設置爲父窗體的回調函數。接下來就是在 iframe 頁面中發送請求,並接收服務器的響應。當 iframe 接收到服務器的反饋並加載完以後,父窗體的回調函數即被調用。
dojo.io.iframe 還有其餘幾個頗有用的函數
create 函數用來在頁面中建立 iframe,參數 fname 表示 iframe 的名字,setSrc 和 doc 函數據此引用建立的 iframe,onloadstr 表示 iframe 加載完成後執行的回調函數,uri:iframe 請求的資源。後兩個參數是可選的,當 uri 爲空時,將加載dojo-module-path/resources/blank.html。
設置指定的 iframe 的 src 屬性,這將致使 iframe 頁面從新加載。 iframe:須要刷新的 iframe 的名字,src:用來刷新 iframe 的頁面 , replace:是否使用 location.replace 方法來更新 iframe 頁面的 url,若是使用 location.replace 方法,則不會在瀏覽器上留下歷史記錄。
獲取指定的 iframe 頁面的 DOM 根節點,有了它能夠對 iframe 頁面進行任意的操做。
dojo.io.iframe 採用了不一樣的思路實現了「異步」發送請求,可是 dojo.io.iframe 使用並很少,由於當頁面中多處須要異步通訊時,在頁面中建立不少的 iframe 並非好的注意。在能使用 xhr 框架的地方儘可能使用 xhr 框架,惟一值得使用 iframe 的地方是發送文件。
XHR 框架中的函數功能強大,使用方便。可是 XHR 框架的函數有一問題就是不能跨域訪問,瀏覽器不容許 XHR 對象訪問其餘域的站點。好比有一個頁面屬於 a.com,在這個頁面中使用 XHR 對象去訪問 b.com 的某一頁面,這是被禁止的。若是使用 XHR 對象來作跨域訪問通常須要服務器端的程序作「中轉」,先由服務器端的程序獲取其餘域的數據,而後瀏覽器再使用 XHR 對象從服務器上獲取這些數據,這種方式即增長了服務器端的開銷,瀏覽器端的效率也不高。
有沒有方法直接在瀏覽器中實現跨域訪問呢?固然有,它就是 script 標籤,使用 script 標籤能夠引用本域或其餘域的文件,只要這些文件最後返回的是 javascript 。返回的 javascript 會當即在瀏覽器中執行,執行結果存儲在本地瀏覽器。這一點很重要,它使得各站點能夠經過 javascript 來發布本身的服務,像 google 的不少的服務都是經過這種方式提供的。 script 標籤不只能夠靜態添加到頁面中,也能夠被動態插入到頁面中,並且經過 DOM 操做方式動態插入的 script 標籤具備與靜態 script 標籤同樣的效果,動態 script 標籤引用的 javascript 文件也會被執行(注意:經過 innerHTML 方式插入的 javascript 是不會被執行的,這一點在前文已經介紹過)。
function createScript() { var element = document.createElement("script" ); element.type = "text/javascript" ; element.src = url; document.getElementsByTagName("head" )[0].appendChild(element); }
清單 8 中的例子展現了動態建立 script 標籤的例子,script 標籤便可以放在頁面的 head 部分,也能夠放在 body 部分。
動態插入 script 標籤的一個問題是如何判斷返回的 Javascript 執行完了,只有在執行完以後才能引用 Javascript 中的對象、變量、調用它中間的函數等。最簡單的方法是「標誌變量法」,即在腳本中插入標誌變量,在腳本最後給這個變量賦值,而在瀏覽器的腳本中判斷這一變量是否已經被賦值,若是已經被賦值則表示返回的腳本已經執行完。可是這種方法缺點也很明顯,首先若是一個頁面有不少的動態 script 標籤,而每一個 script 標籤引用的 javascript 都使用一個標誌變量,那就有不少變量須要判斷,並且這些變量的命名可能衝突,由於這些 Javascript 是由不一樣的組織、公司提供的,難保不產生衝突。另外在瀏覽器本地腳本中須要輪詢這些變量的值,雖然能夠實現,但實在不是高明的作法。目前被普遍使用的是另外一種方法:JSONP(JSON with Padding)。 JSON 表示返回的 Javascript 其實就是一 JSON 對象,這是使用 JSONP 這種方式的前提條件。 Padding 表示在 JSON 對象前要附加上一些東西,到底是什麼呢?請往下看!
JSONP 的思路很簡單,與其讓瀏覽器腳原本判斷返回的 Javascript 是否執行完畢,不如讓 Javascript 在執行完畢以後自動調用咱們想要執行的函數。是否是想起了學習面向對象設計中的「依賴倒置」原則時的那句名言:「Don't call us, we will call you 」。使用 JSONP 這種方法,只須要在原來的 Javascript 引用連接上加上一個參數,把須要執行的回調函數傳遞進去。請看下面的兩個 script 標籤。
若是 http://url/js.php?parameter= … . 返回的是 JSON 對象 {result:「hello,world」} , 那麼第二個 script 標籤返回的則是 mycallback({result: 」 hello, world 」 }),這一函數將在寫入到瀏覽器後當即被執行,這不就實現了在 Javascript 執行完以後自動調用咱們須要執行的回調函數了嗎?
介紹了這麼多動態腳本的背景知識,終於來到了 Dojo 對動態腳本的支持上。 Dojo 即支持標誌變量法,也支持 JSONP 方式。清單 9 是使用標誌變量法的動態 script 的例子,在這個例子中使用了 dojo.io.script.get 函數。
<html> <head> <script src="../dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script> dojo.require("dojo.io.script" ); </head> <body> <script> dojo.io.script.get({ url:"data.php" ,checkString:"test_01" , handle:function(response, ioArgs) { greetFromServer("hello, world"); } }); </script> </body> </html>
dojo.io.script.get 函數的使用方式和參數是否是與 xhrGet 很類似?只有 checkString 是 xhrGet 所特有的,checkString 正是「標誌變量法」的關鍵,checkString 表示從服務器返回的 javascript 須要定義的變量。清單 10 展現了使用 PHP 編寫的服務器端的腳本,它輸出了一段 javascript,在這段 javasript 的最後給變量 test_01 賦值。而清單 9 中 dojo.io.script.get 函數的 handle 指向的回調函數又調用了這段 javascript 中定義的函數 greetFromServer() 。只有在 test_01 被賦值後,調用 greetFromServer 纔是安全的。
<?php echo "vartest_01;"; echo "function greetFromServer(name) {alert(name)}"; echo "test_01='defined'"; ?>
dojo.io.script.get 函數也支持 JSONP 方式,當 dojo.io.script.get 函數的參數對象使用了 callbackParamName 屬性時,表示它工做在 JSONP 方式下。 callbackParamName 表示在 url 中添加回調函數名的參數名稱,有點拗口,可是看了下面 dojo.io.script.get 函數在頁面中動態建立的 script 標籤一切就都清楚了,最終出如今 URL 中的是 callbackName,而不是 callbackParamName 。
<script src="data2.php?callbackName=dojo.io.script.jsonp_dojoIoScript1._jsonpCallback" >
<html><head> <script src="../dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script> dojo.require("dojo.io.script" ); </head> <body> <script> dojo.io.script.get({ url:"data2.php", callbackParamName: "callbackName" , handle: function(response, ioArgs) { document.write(response.greet); } }); } </script> </body></html>
Dojo 會自動建立一個名爲 dojo.io.script.jsonp_dojoIoScript1._jsonpCallback 的 javascript 函數,這個函數其實什麼都不作,只是做爲一個回調函數傳給服務器端程序。 php 的服務器端程序如清單 12 所示,callbackName 像瀏覽器和服務器之間的一個「信令」,服務器端必須返回對 callbackName 所表明的函數的調用,由於 Dojo 會檢查它是否被調用過。
因此服務器端返回的是 dojo.io.script.jsonp_dojoIoScript1._jsonpCallback({greet:’hello, world’}) 。參數 {greet:’hello, world’} 正是要返回到瀏覽器的 JSON 對象。
<?php $cb = $_GET["callbackName"]; echo $cb."({greet:'hello, world'});"; ?>
清單 11 所示程序的輸出爲:hello, world,由此能夠看出,response 參數就是從服務器端返回的 JSON 對象,服務器端的 JSON 對象終於成功的傳遞到瀏覽器了。前面介紹了這麼多的機制都是爲了使這個 JSON 對象安全返回到瀏覽器中。固然你能夠在服務器端返回任何數據,好比直接返回一個字符串,但此時 response 就變成字符串了,固然也就不能再叫 JSONP 了,由於 JSONP 特指返回的是 JSON 對象。
dojo.io.script 對象中除了 get 函數以外,還有 attach,和 remove 兩個函數
建立動態 script 標籤,標籤的 id 由參數 id 指定,src 由 url 指定。
刪除 id 表明 script 標籤。
本文介紹了 Dojo 中三種瀏覽器與服務器交互的方式,這三種方式各有優缺點,可是在使用方式卻出奇的一致; xhr 框架的函數,dojo.io.iframe、dojo.io.script 對象的函數使用的 JSON 對象參數也極其類似,並且淺顯易懂。 Dojo 設計者的這一良好設計極大的減輕了開發人員的學習負擔,做爲框架開發人員應該瞭解這一理念。表 2 對這三種方式從三個方面進行了比較。
支持的 HTTP 請求類型 | 指望的輸出 | 跨域 | |||
XHR | Get, post, delete, put | text, json, xml, javascript … | N | N | |
iframe | Get, post | html | N | N | |
script | Get | javascript | Y | Y |