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