javascript效能優化(7)
Ajax 非同步 JavaScript 和 XML
Ajax 是高效能 JavaScript 的基石。它可以通過延遲下載大量資源使頁面載入更快。它通過在客戶端和服 務器之間非同步傳送資料,避免頁面集體載入。它還用於在一次 HTTP 請求中獲取整個頁面的資源。通過選 擇正確的傳輸技術和有效的資料格式,你可以顯著改善使用者與網站之間的互動。
資料傳輸
有5種常用的技術用於向伺服器請求資料:
- XMLHttpRequest (XHR)
- Dynamic script tag insertion 動態指令碼標籤插入
- iframes
- Comet
- Multipart XHR 多部分的 XHR
現在常使用的三種技術是XHR、動態指令碼標籤插入、多部分的 XHR ;剩餘兩種就不做討論。
XMLHttpRequest
var url = '/data.php';
var params = ['id=934875', 'limit=20'];
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState === 3) { // Some, but not all, data has been received.
// Process the data here...
}
else if (req.readyState === 4) {
var responseHeaders = req.getAllResponseHeaders(); // Get the response headers.
var data = req.responseText; // Get the data.
// Process the data here...
}
}
req.open('GET', url + '?' + params.join('&'), true);
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // Set a request header.
req.send(null); // Send the request.
readyState 等於3 “ ”,表示此時正在與伺服器互動,響應報文還在傳輸中。這就是所謂的“流”,他是提高資料請求效能的強大工具。readyState 等於4,表示整個響應報文已經收並完,可用於操作。
使用 POST,還是 GET
如果請求不改變伺服器狀態只是取回資料,則用get;get請求被緩衝起來,如果你多次提取相同的資料可提高效能。
只有當URL和引數的長度超過了2048個字元時才使用POST提取資料;因為IE限制URL的長度,過長將導致請求引數被截斷。
動態指令碼標籤插入
var scriptElement = document.createElement('script');
scriptElement.src = 'http://any-domain.com/javascript/lib.js';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
在lib.js檔案中,將呼叫jsonCallback函式組裝資料;
function jsonCallback(jsonString) {
var data = ('(' + jsonString + ')');
// Process the data here...
}
jsonCallback({"status": 1, "colors": ["#fff", "#000", "#ff0000"]});
Multipart XHR 多部分XHR
多部分 XHR(MXHR)允許你只用一個 HTTP 請求就可以從伺服器端獲取多個 資源。它通過將資源(可以是 CSS 檔案,HTML 片段,JavaScript 程式碼,或 base64 編碼的圖片)打包成一 個由特定分隔符界定的大字串,從伺服器端傳送到客戶端。JavaScript 程式碼處理此長字串,根據它的 媒體型別和其他“資訊頭”解析出每個資源.
由於 MXHR 響應報文越來越大,有必要在每個資源收到時立刻處理,而不是等待整個響應報文接收完 成。這可以通過監聽 readyState 3 實現:
var req = new XMLHttpRequest();
var getLatestPacketInterval, lastLength = 0;
req.open('GET', 'rollup_images.php', true);
req.onreadystatechange = readyStateHandler;
req.send(null);
function readyStateHandler (){
if (req.readyState === 3 && getLatestPacketInterval === null) { // Start polling.
getLatestPacketInterval = window.setInterval(function () {
getLatestPacket();
}, 15);
}
if (req.readyState === 4) { // Stop polling.
clearInterval(getLatestPacketInterval); // Get the last packet.
getLatestPacket();
}
}
function getLatestPacket() {
var length = req.responseText.length;
var packet = req.responseText.substring(lastLength, length);
processPacket(packet);
lastLength = length;
}
當 readyState 3 第一次發出時,啟動了一個定時器。每隔 15 毫秒檢查一次響應報文中的新資料。資料片 段被收集起來直到發現一個分隔符,然後一切都作為一個完整的資源處理.
缺點:
- 資源不能被瀏覽器快取。
- 老版本的 Internet Explorer 不支援 readyState 3 或 data: URL。Internet Explorer 8 兩個都支 持,但在 Internet Explorer 6 和 7 中必須設法變通。
傳送資料
當使用 XHR 將資料發回伺服器時,它比使用 GET 要快。這是因為對少量資料而言,向伺服器傳送一個 GET 請求要佔用一個單獨的資料包。另一方面,一個 POST 至少傳送兩個資料包,一個用於資訊頭。另一 個用於 POST 體。POST 更適合於向伺服器傳送大量資料,即因為它不關心額外資料包的數量,又因為 Internet Explorer 的 URL 長度限制,它不可能使用過長的 GET 請求。
資料格式
這裡只看了JSON,JSONP;其他的像XML等,不做分析。
常見的json格式
[
{"id":1, "username":"alice", "realname": "Alice Smith", "email":"alice@alicesmith.com"},
{"id":2, "username":"bob", "realname": "Bob Jones", "email":"bob@bobjones.com"},
{"id":3, "username":"carol", "realname": "Carol Williams","email":"carol@carolwilliams.com"},
{"id":4, "username":"dave", "realname": "Dave Johnson", "email":"dave@davejohnson.com"}
]
陣列格式的json
[
[ 1, "alice", "Alice Smith", "alice@alicesmith.com" ],
[ 2, "bob", "Bob Jones", "bob@bobjones.com" ],
[ 3, "carol", "Carol Williams", "carol@carolwilliams.com" ],
[ 4, "dave", "Dave Johnson", "dave@davejohnson.com" ]
]
陣列形式的 JSON 在每一項中均獲勝,它檔案尺寸小,下載快,平均解析時間短。儘管解析函式 不得不遍歷列表中所有 5’000 個單元,它還是快出了 30%。
避免使用 JSON-P的原因:因為 JSON-P 必須是可執行的 JavaScript,它使用動態 指令碼標籤注入技術可在任何網站中被任何人呼叫。從另一個角度說,JSON 在執行之前並不是有效的 JavaScript,使用 XHR 時只是被當作字串獲取。不要將任何敏感的資料編碼為 JSON-P,因為你無法確定 它是否包含私密資訊,或者包含隨機的 URL 或 cookie。
資料格式總結
總的來說越輕量級的格式越好,好是 JSON 和字元分隔的自定義格式。如果資料集很大或者解析時間 成問題,那麼就使用這兩種格式之一:
- JSON-P 資料,用動態指令碼標籤插入法獲取。它將資料視為可執行的 JavaScript 而不是字串,解析速度 極快。它能夠跨域使用,但不應涉及敏感資料。
- 字元分隔的自定義格式,使用 XHR 或動態指令碼標籤插入技術提取,使用 split()解析。此技術在解析非常 大資料集時比 JSON-P 技術略快,而且通常檔案尺寸更小。
下載和解析時間對比。
Ajax 效能嚮導
快取資料
快的 Ajax 請求就是你不要用它。有兩種主要方法避免發出一個不必要的請求:
1. 在伺服器端,設定 HTTP 頭,確保返回報文將被快取在瀏覽器中。
2. 在客戶端,於本地快取已獲取的資料,不要多次請求同一個資料。
第一種技術容易設定和維護,而第二個給你大程度的控制。
設定 HTTP 頭
在發起請求時使用 GET 方法。但這還不充分, 你必須在響應報文中傳送正確的 HTTP 頭。Expires 頭告訴瀏覽器應當快取響應報文多長時間.。其值是一個 日期,當過期之後任何對該 URL 發起的請求都不再從快取中獲得,而要重新訪問伺服器。一個 Expires 頭 如下:
Expires: Mon, 28 Jul 2014 23:30:00 GMT
Expires 頭中的日期是 GMT 日期。它在 PHP 中使用如下程式碼設定:
$lifetime = 7 * 24 * 60 * 60; // 7 days, in seconds.
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $lifetime) . ' GMT');
//這將告訴瀏覽器快取此資料 7 天。
本地儲存資料
除了依賴瀏覽器處理快取之外,你還可以用手工方法實現它,直接儲存那些從伺服器收到的響應報文。 可將響應報文存放在一個物件中,以 URL 為鍵值索引它。這是一個 XHR 封裝,它首先檢查一個 URL 此 前是否被取用過,如果有直接調取之前的快取;沒有的話,就重新獲取。
var localCache = {};
function xhrRequest(url, callback) { // Check the local cache for this URL.
if (localCache[url]) {
callback.success(localCache[url]);
return;
} // If this URL wasn't found in the cache, make the request.
var req = createXhrObject();
req.onerror = function () {
callback.error();
};
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.responseText === '' || req.status == '404') {
callback.error();
return;
} // Store the response on the local cache.
localCache[url] = req.responseText;
callback.success(req.responseText);
}
}
;
req.open("GET", url, true);
req.send(null);
}
Summary 總結
- 高效能 Ajax 包括:知道你專案的具體需求,選擇正確的資料格式和與之相配的傳輸技術。
- 作為資料格式,純文字和 HTML 是高度限制的,但它們可節省客戶端的 CPU 週期。XML 被廣泛應用 普遍支援,但它非常冗長且解析緩慢。JSON 是輕量級的,解析迅速(作為原生程式碼而不是字串),交 互性與 XML 相當。字元分隔的自定義格式非常輕量,在大量資料集解析時速度快,但需要編寫額外的 程式在伺服器端構造格式,並在客戶端解析。
- 當從頁面域請求資料時,XHR 提供完善的控制和靈活性,儘管它將所有傳入資料視為一個字串, 這有可能降低解析速度。另一方面,動態指令碼標籤插入技術允許跨域請求和本地執行 JavaScript 和 JSON, 雖然它的介面不夠安全,而且不能讀取資訊頭或響應報文程式碼。多部分 XHR 可減少請求的數量,可在一次響應中處理不同的檔案型別,儘管它不能快取收到的響應報文。當傳送資料時,影像燈標是簡單和有效的方法。XHR 也可用 POST 方法傳送大量資料。
一些建議:
- 減少請求數量,可通過 JavaScript 和 CSS 檔案打包,或者使用 MXHR。
- 縮短頁面的載入時間,在頁面其它內容載入之後,使用 Ajax 獲取少量重要檔案。
- 確保程式碼錯誤不要直接顯示給使用者,並在伺服器端處理錯誤。
- 學會何時使用一個健壯的 Ajax 庫,何時編寫自己的底層 Ajax 程式碼。
相關文章
- Javascript 效能優化JavaScript優化
- javascript效能優化JavaScript優化
- javascript效能優化(8)JavaScript優化
- javascript效能優化(9)JavaScript優化
- javascript效能優化(10)JavaScript優化
- 前端效能優化JavaScript篇前端優化JavaScript
- JavaScript 操作DOM效能優化JavaScript優化
- 幾個 JavaScript 效能優化小 TipJavaScript優化
- 淺談JavaScript程式碼效能優化JavaScript優化
- PHP7效能優化筆記PHP優化筆記
- JavaScript 前端效能優化之事件防抖JavaScript前端優化事件
- JavaScript 前端效能優化之事件節流JavaScript前端優化事件
- 淺談JavaScript程式碼效能優化2JavaScript優化
- 【前端效能優化】高效能JavaScript讀書筆記前端優化JavaScript筆記
- Web 效能優化:理解及使用 JavaScript 快取Web優化JavaScript快取
- 【前端效能優化】vue效能優化前端優化Vue
- 【譯】Web 效能優化:理解及使用 JavaScript 快取Web優化JavaScript快取
- [譯] JavaScript 如何工作:渲染引擎和效能優化技巧JavaScript優化
- 效能優化優化
- JavaScript 前端效能優化小竅門例項彙總JavaScript前端優化
- 前端效能優化(JS/CSS優化,SEO優化)前端優化JSCSS
- Android效能優化——效能優化的難題總結Android優化
- [效能優化]DateFormatter深度優化探索優化ORM
- 前端效能優化 --- 圖片優化前端優化
- 效能優化|Tomcat 服務優化優化Tomcat
- Android 效能優化 ---- 啟動優化Android優化
- Android效能優化----卡頓優化Android優化
- 前端效能優化:細說JavaScript的載入與執行前端優化JavaScript
- JavaScript 工作原理之十一-渲染引擎及效能優化小技巧JavaScript優化
- JavaScript效能最佳化JavaScript
- java效能優化Java優化
- react效能優化React優化
- Canvas效能優化Canvas優化
- UI效能優化UI優化
- mongodb效能優化MongoDB優化
- Android效能優化Android優化
- EF效能優化優化
- TableView效能優化View優化