摘要:XMLHttpRequest javascript高性能的Ajax應該考慮數(shù)據(jù)傳輸技術和數(shù)據(jù)格式,以及其他的如數(shù)據(jù)緩存等優(yōu)化技術。一、請求數(shù)據(jù)請求數(shù)據(jù)的常用技術有XHR,動態(tài)腳本注入、Multipart XHR、iframes、Comet五種,其中前三種比較常見,后兩種往往在比較極端的情況下使用。1、XMLHttpRequest這個是首選技術,有兩種方式,post和get, G
XMLHttpRequest javascript
高性能的Ajax應該考慮數(shù)據(jù)傳輸技術和數(shù)據(jù)格式,以及其他的如數(shù)據(jù)緩存等優(yōu)化技術。
一、請求數(shù)據(jù)
請求數(shù)據(jù)的常用技術有XHR,動態(tài)腳本注入、Multipart XHR、iframes、Comet五種,其中前三種比較常見,后兩種往往在比較極端的情況下使用。
1、XMLHttpRequest
這個是首選技術,有兩種方式,post和get,
GET:一般針對那些不會改變服務器狀態(tài),只獲取數(shù)據(jù)的請求,GET請求的數(shù)據(jù)會被緩存起來,對于需要多次請求同一數(shù)據(jù)的情況,有助于提升性能。
缺點:請求的url加上參數(shù)長度接近或超過2048字符時,會導致URL被截斷(在IE中,IE限制url長度,IE對URL長度的限制是2083字節(jié)(2K+35)。對于其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決于操作系統(tǒng)的支持。),這時需要使用post。
POST:理論上POST沒有限制,可用于較大量的數(shù)據(jù)傳輸。
注:通過XHR請求數(shù)據(jù)時,無法訪問外域數(shù)據(jù)
2、動態(tài)腳本注入
克服了XHR的限制:能夠跨域請求數(shù)據(jù)
通過創(chuàng)建script標簽,將src指向不同域的url即可。
與XHR相比:
(1) 動態(tài)腳本注入無法設置頭信息,
(2) 只能使用get方式,不能使用post方式,
(3) 不能訪問請求的頭信息,也不能將響應消息作為字符串來處理,響應消息一般是可執(zhí)行的javascript腳本(其他待返回的XML、JSON或其他格式的數(shù)據(jù)都要封裝在一個回調(diào)函數(shù)中)
3、Multipart XHR
MXHR允許客戶端只用一個HTTP請求從服務器端向客戶端傳送多個資源。它通過在服務器端將多個資源(css文件、HTML片段、js代碼、base64編碼的圖片)打包成一個由雙方約定的特定字符分割的長字符串發(fā)送到客戶端。然后,在客戶端根據(jù)那個特定的字符將這個長字符串解析成各個資源。
例如:
$dataArr=array(); $images=array('1.jpg','2.jpg','3.jpg'); foreach($images as $img){ $file=fopen($img,'r'); $imgdata=fread($file,filesize($img)); $imgdata=base64_encode($imgdata); fclose($file); array_push($dataArr,$imgdata); } $newchar=chr(1); echo implode($newchar,$dataArr);//使用一個不會出現(xiàn)在base64中的一個字符將各個圖片的base64編碼連成一個長字符串
數(shù)據(jù)到達客戶端后,再進行解析
function splitImage(imgstring){ var imgdata=imgstring.split(\u0001'); //將字符串分割 var img=document.createElement('img'); for(var i=0,len=imgdata.length;i<len;i++){ var tmpimg=img.cloneNode(); tmpimg.src="data:image/jpeg;base64,"+imgdata[i]; document.getElementById('div1').appendChild(tmpimg); } }
由于一次性請求的資源多,所以不必等待所有資源都返回在進行處理,可以根據(jù)readyState狀態(tài)值監(jiān)測響應狀態(tài),當readyState為3時,就對接收到的部分數(shù)據(jù)進行處理。
優(yōu)點:一次可以請求多個資源,提升性能
缺點:獲取的資源不能被瀏覽器緩存(以為資源是以字符串形式返回的)
IE7以下版本不支持readyState為3的狀態(tài)
二、發(fā)送數(shù)據(jù)
1、XHR
GET方式受瀏覽器的最大URL尺寸限制,當上傳數(shù)據(jù)量較大時,用POST方式。
對于少量數(shù)據(jù),GET方式會更快,因為一個GET請求往服務器只發(fā)送一個數(shù)據(jù)包,而一個POST請求,至少要發(fā)送兩個數(shù)據(jù)包,一個裝載頭信息,一個裝載
POST正文。
2、Beacons 信標
Beacons和動態(tài)腳本注入類似,先創(chuàng)建一個image對象,把src指向服務器上腳本的url,該url包含了通過get方式向服務器上傳的鍵值對數(shù)據(jù)。
var params=["namme=lc","id=1"]; var url="/test.php"; var beacons=new Image(); beacons.src=url+"?"+params.join("&"); //注:并沒有將它插入DOM中 所以圖片是不顯示的
服務器端接收到數(shù)據(jù)后,無需向客戶端返回回饋信息。但是也可以在服務端做出不同的響應,比如返回1px寬的空白圖片代表成功接收,2px寬的空白圖片代表接收失敗。
beacons.onload=function (){ if(this.width==1){ //成功 }else if(this.width==2){ //失敗 } }
使用信標,是向服務器回傳數(shù)據(jù)最快最有效的方式,服務器無需返回任何響應正文。
缺點:無法使用POST方式,上傳數(shù)據(jù)量有限制,服務器的響應類型很有限。
所以,如果要往客戶端返回大量數(shù)據(jù),只能用XHR
如果只關心發(fā)送數(shù)據(jù)到服務器(可能要返回少量信息),可以使用圖片信標。
Beacons方法很巧妙,比如它可以利用image對象的src屬性,瀏覽器創(chuàng)建一個新的image對象會去加載它的src屬性值,如果把我們要傳遞給服務器的參數(shù)使用&連接起來組成GET方式的URL,然后賦給src,那么瀏覽器在發(fā)出請求的時候就可以把我們要傳遞的參數(shù)傳遞給服務端。我們可以在服務端做出不同的響應,比如返回1px寬的空白圖片代表成功接收,2px寬的空白圖片代表接收失敗。這種傳遞數(shù)據(jù)的方法一般用于統(tǒng)計用戶行為等非必須完成的請求。
補充:
POST的安全性要比GET的安全性高。注意:這里所說的安全性和上面GET提到的“安全”不是同個概念。上面“安全”的含義僅僅是不作數(shù)據(jù)修改,而這里安全的含義是真正的Security的含義,比如:通過GET提交數(shù)據(jù),用戶名和密碼將明文出現(xiàn)在URL上,因為(1)登錄頁面有可能被瀏覽器緩存,(2)其他人查看瀏覽器的歷史紀錄,那么別人就可以拿到你的賬號和密碼了,除此之外,使用GET提交數(shù)據(jù)還可能會造成Cross-site request forgery攻擊。
3、數(shù)據(jù)格式
服務器端與客戶端進行數(shù)據(jù)傳輸時,數(shù)據(jù)的格式會影響其下載速度和解析速度,一般來說JSON形式和字符分隔的自定義格式是最好的。XML、HTML一般會增加數(shù)據(jù)量,解析較慢。
大數(shù)據(jù)量且要求解析時間的話,可以選擇:
a、JSON-P數(shù)據(jù),使用動態(tài)腳本獲取,把數(shù)據(jù)當做js腳本運行而不是字符串,解析速度極快,能跨域使用,涉及敏感數(shù)據(jù)時不應使用
b、自定義數(shù)據(jù),用XHR或動態(tài)腳本注入獲取,通過split解析,比JSON-P略快
4、數(shù)據(jù)緩存技術
一是,在服務器端,設置HTTP頭信息,使用瀏覽器緩存
一是,在客戶端,把獲取的信息存儲到本地,避免再次請求
設置HTTP頭信息
$lifetime=7*24*60*60; header('Expires'.gmdate('D,d M Y H:i:s',time()+$lifetime).'GMT');
客戶端實現(xiàn):
把響應信息保存到一個本地對象中