經(jīng)過11個半小時的長途飛行,還有在韓國的一夜煎熬,終于踏上了祖國的國土。回家的感覺真好。
不得不提一下在韓國的待遇,因為要過夜,機場提供賓館住宿,飛機于韓國當(dāng)?shù)貢r間晚上9點半到達(dá),結(jié)果凌晨2點多我才躺在賓館的床上。
條件還是不錯,是個5星的賓館,于是按計劃給沒有同行的老婆打個電話,聊了大概20分鐘,可是第二天退房的時候竟然要了我1萬多korean wan,合人民幣100左右。我算是張記性了,以后還是買張卡再打電話吧。
回國稍微休息了一天,把Dojo book第一章補充翻譯了出來。
譯者序:
Dojo book目前還在不斷更新和補充中,我會盡量跟上原著的腳步,給大家最新的信息。
更新我會用隨筆寫出來,同時也會更新原文章。
I/O
dojo.io.blind介紹在我們制作dojo的時候,目的是讓用戶和開發(fā)者都能享受到DHTML程序。在很多朋友的支持下,特別是Aaron
Boodman和Mark Anderson,我們已經(jīng)找到了解決可用性的方法。我們提供了一個單獨的易用的API和一個包裝類,這個類只需要兩個文件。dojo.io包提供了對XMLHTTP和一些其他更復(fù)雜的傳輸結(jié)構(gòu)的支持。
在dojo.io包中我們一般最常使用的是dojo.io.bind()方法。dojo.io.blind()是一個標(biāo)準(zhǔn)的異步的請求API,它包含了各種傳輸層(transport layers),包括queues of iFrames,XMLHTTP,mod_pubsub,LivePage等等。Dojo會試圖為當(dāng)前的請求選擇最合適的傳輸方法,因為在做網(wǎng)站時一般不會使用到其他傳輸,所以我們只用到XMLHTTP。dojo接受一個匿名的類,但是在知道這個類的屬性的情況下,把它作為方法參數(shù)(function argument)。下面的代碼是創(chuàng)建一個請求(request),這個請求會從URL返回原始的字符串。
dojo.io.bind({
????url:?"http://foo.bar.com/sampleData.txt",
????load:?function(type,?data,?evt){?/*do?something?w/?the?data?*/?},
????mimetype:?"text/plain"
});
這就是全部,你提供了一個數(shù)據(jù)地址,還有一個當(dāng)你得到返回值時要執(zhí)行的function。但是如果在請求過程中出錯了怎么辦呢?我們再來創(chuàng)建一個register來解決:
dojo.io.bind({
????url:?"http://foo.bar.com/sampleData.txt",
????load:?function(type,?data,?evt){?/*do?something?w/?the?data?*/?},
????error:?function(type,?error){?/*do?something?w/?the?error*/?},
????mimetype:?"text/plain"
});
同樣也可以只創(chuàng)建一個單獨的handler來解決:
dojo.io.bind({
????url:?"http://foo.bar.com/sampleData.txt",
????handle:?function(type,?data,?evt){
????????if(type?==?"load"){
????????????//?do?something?with?the?data?object
????????}else?if(type?==?"error"){
????????????//?here,?"data"?is?our?error?object
????????????//?respond?to?the?error?here
????????}else{
????????????//?other?types?of?events?might?get?passed,?handle?them?here
????????}
????},
????mimetype:?"text/plain"
});
下面的代碼提交一段javascript程序段,然后讓服務(wù)器運行它,一般我們這么做是為了加速程序運行,注意
mimetype:
dojo.io.bind({
????url:?"http://foo.bar.com/sampleData.js",
????load:?function(type,?evaldObj){?/*?do?something?*/?},
????mimetype:?"text/javascript"
});
如果你想確保程序使用XMLHTTP,可以這樣寫:
dojo.io.bind({
????url:?"http://foo.bar.com/sampleData.js",
????load:?function(type,?evaldObj){?/*?do?something?*/?},
????mimetype:?"text/plain",?//?get?plain?text,?don't?eval()
????transport:?"XMLHTTPTransport"
});
Being a jack-of-all-trades,
bind() also supports the submission of forms via a
request (with the single caveat that it won't do file upload over XMLHTTP):
作為一個jack-of-all-trades(萬事通),bind()同樣支持來自于表單提交的數(shù)據(jù)。
dojo.io.bind({
????url:?"http://foo.bar.com/processForm.cgi",
????load:?function(type,?evaldObj){?/*?do?something?*/?},
????formNode:?document.getElementById("formToSubmit")
});
以上只是一些最基本的,其實這些可以不用全部由開發(fā)者自定義。
RPC你可以看到,Dojo通過dojo.io.bind提供了簡單,強大的方法使用多種多樣的I/O functions。但是在開發(fā)過程中,程序員會調(diào)用很多很多I/O,這同時會給服務(wù)器和客戶端加重負(fù)擔(dān)。Dojo的RPC服務(wù)就是為了減少負(fù)擔(dān),易用,精簡代碼而生的。
RPC的全名是Remote Procedre Calls,或者Remote Method Invocation,(譯者:遠(yuǎn)程method調(diào)用)。最基本的,RPC允許開發(fā)者調(diào)用在遠(yuǎn)程服務(wù)器上的方法(method)。Dojo不僅提供了基本的RPC client包,而且還擴(kuò)展了它,使它支持JSON-RPC服務(wù)和YAHOO服務(wù)。同時你也可以自己寫出相對于其他服務(wù)的類。
我們假定有一個需要調(diào)用服務(wù)器端程序的小程序,假設(shè)要調(diào)用add(x,y)和subtract(x,y)。在沒有特殊情況的條件下,我們的客戶端會這樣寫:
add?=?function(x,y)?{
????request?=?{x:?x,?y:?y};
????dojo.io.bind({
????????????url:?"add.php",
????????????load:?onAddResults,
????????????mimetype:?"text/plain",
????????content:?request
????});
}
subtract?=?function(x,y)?{
????request?=?{x:?x,?y:?y};
????
????dojo.io.bind({
????????????url:?"subract",
????????????load:?onSubtractResults,
????????????mimetype:?"text/plain"
????????content:?request
????});
}

你看,這不是很難。但是無論是我們讓服務(wù)器運行add和subtract還是讓客戶端自己計算,這只是一個非常簡單的程序。如果我們要調(diào)用在服務(wù)器上30個不同method會怎么樣呢?我猜我們可能要重復(fù)的寫幾乎一樣的代碼一遍又一遍,每次都要創(chuàng)建一個請求類(request object),設(shè)定URL,設(shè)定變量等等。這不僅容易出錯,而且還很枯燥。
Dojo的RPC客戶端簡化了這個過程:
{
????"serviceType":?"JSON-RPC",?
????"serviceURL":?"rpcProcessor.php",?
????"methods":[?
????????{
????????????"name":?"add",?
????????????"parameters":[
????????????????{"name":?"x"},
????????????????{"name":?"y"}????
????????????]
????????},
????????{
????????????"name":?"subtract",?
????????????"parameters":[
????????????????{"name":?"x"},
????????????????{"name":?"y"}????
????????????]
????????}
????]
}
以上就是對于服務(wù)器的定義。一旦定義創(chuàng)建完畢,其他的事情就簡單了,我們還可以創(chuàng)建一個類:
var?myObject?=?new?dojo.rpc.JsonService?(defintion);
要使用服務(wù)器的方法:
myObject.add(3,5);
我敢打賭你會在想“我不是只調(diào)用方法就夠了,我還有得到計算的結(jié)果。”你是對的,但這也是非常容易的。服務(wù)器端的myObject.add()會返回一個延緩類(deferred object)。Twisted Python用戶可能對延緩類(deferred object)很熟悉,延緩類(deferred object)允許開發(fā)者根據(jù)返回數(shù)據(jù)的類型附加一個或更多的回叫(callbacks)和錯誤處理(errbacks)。這里有一個簡單的例子:
var?myDeferred?=?myObject.add(3,5);
myDeferred.addCallback(myCallbackMethod);
我們把mycallbackmethod作為回叫添加到我們的延緩類mydeferred。這時,8會被傳遞進(jìn)mycallbackmethod。另一方面,我們也可以添加一個errback method來處理服務(wù)器返回的出錯信息。我們隨意添加回叫方法(callback),多少都可以,它們會按照我們定義的順序被調(diào)用。
以上的例子都是圍繞dojo.rpc.JsonService展開的。我們還可以使用dojo.rpc.YahooService,規(guī)范和結(jié)構(gòu)都是一樣的。這兩個類都是繼承了dojo.rpc.RpcService。要創(chuàng)建自己的類會在第二章中詳細(xì)介紹。(譯者:第二章原著還沒有完成)