讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議142:比較常用的服務器發送數據方法 >

建議142:比較常用的服務器發送數據方法

有時可以不關心接收數據,只要將數據發送給服務器即可。可以發送用戶的非私有信息以備日後分析,或者捕獲所有腳本錯誤,然後將有關細節發送給服務器進行記錄和提示。當數據只需發送給服務器時,有兩種應用得非常廣泛的技術:XHR和燈標。

(1)XHR

XHR主要用於從服務器獲取數據,也可以用來將數據發回。可以用GET或POST方式發回數據,以及任意數量的HTTP信息頭。在向服務器發回的數據量超過瀏覽器的最大URL長度時XHR特別有用。在這種情況下,可以用POST方式發回數據:


var url='/data.php';

var params=['id=934875','limit=20'];

var req=new XMLHttpRequest;

req.onerror=function{

};

req.onreadystatechange=function{

if(req.readyState==4){

}

};

req.open('POST',url,true);

req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

req.setRequestHeader('Content-Length',params.length);

req.send(params.join('&'));


在上面代碼中,如果通信失敗,則什麼也不做。當使用XHR捕獲登錄用戶統計信息時,這麼做通常沒什麼問題,但是,如果發送到服務器的是至關重要的數據,那麼可以添加代碼在失敗時重試:


function xhrPost(url,params,callback){

var req=new XMLHttpRequest;

req.onerror=function{

setTimeout(function{

xhrPost(url,params,callback);

},1000);

};

req.onreadystatechange=function{

if(req.readyState==4){

if(callback&&typeof callback==='function'){

callback;

}

}

};

req.open('POST',url,true);

req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

req.setRequestHeader('Content-Length',params.length);

req.send(params.join('&'));

}


使用XHR將數據發回服務器比使用GET要快,這是因為對少量數據而言,向服務器發送一個GET請求要佔用一個單獨的數據包。另外,一個POST至少發送兩個數據包,一個用於信息頭,另一個用於POST體。POST更適合於向服務器發送大量數據,既因為它不關心額外數據包的數量,又因為IE的URL長度限制,不可能使用過長的GET請求。

(2)燈標

燈標與動態腳本標籤插入非常類似。JavaScript創建一個新的Image對象,將src設置為服務器上一個腳本文件的URL,該URL包含通過GET格式傳回的鍵值對數據。注意,這裡並沒有創建img元素或將它們插入到DOM中。


var url='/status_tracker.php';

var params=['step=2','time=1248027314'];

(new Image).src=url+'?'+params.join('&');


服務器得到此數據並保存下來,不必向客戶端返回什麼,因此沒有實際的圖像顯示。這是將信息發回服務器的最有效方法,開銷很小,而且任何服務器端錯誤都不會影響客戶端。

由於簡單的圖像燈標不能發送POST數據,所以應將URL長度限制在一個相當小的字符數量上。當然也可以用非常有限的方法接收返回數據,可以監聽Image對象的load事件,判斷服務器端是否成功接收了數據。還可以檢查服務器返回圖片的寬度和高度(如果返回了一張圖片)並用這些數字通知服務器的狀態。例如,寬度為1表示成功,2表示重試等。

如果不需要為此響應返回數據,那麼應當發送一個204 No Content響應代碼,表示無消息正文,從而阻止客戶端繼續等待永遠不會到來的消息體。


var url='/status_tracker.php';

var params=['step=2','time=1248027314'];

var beacon=new Image;

beacon.src=url+'?'+params.join('&');

beacon.onload=function{

if(this.width==1){

//成功處理

}else if(this.width==2){

//失敗處理

}

};

beacon.onerror=function{

//錯誤處理

};


燈標是向服務器回送數據最快和最有效的方法。因為服務器根本不需要發回任何響應正文,所以不必擔心客戶端下載數據。使用燈標的唯一缺點是接收到的響應類型是受限的。如果需要向客戶端返回大量數據,那麼使用XHR。如果只關心將數據發送到服務器端,那麼使用圖像燈標。