提高AJAX客户端响应速度
很多时候系统响应速度的降低都是由不够合理的界面设计和不够高效的编程习惯造成的。下面我们就来分析几个AJAX开发过程中需要时刻注意的环节。
合理的使用客户端编程和远程过程调用。
客户端的编程主要都是基于JavaScript的。而JavaScript是一种解释型的编程语言,它的运行效率相对于Java等都要稍逊一筹。同时JavaScript又是运行在浏览器这样一个严格受限的环境当中。因此开发人员对于哪些逻辑可以在客户端执行应该有一个清醒的认识。
在实际的应用中究竟应该怎样使用客户端编程,这依赖于开发人员的经验判断。这里很多问题是只可意会的。由于篇幅有限,在这里我们大致归纳出下面这几个注意事项:
尽可能避免频繁的使用远程过程调用,例如避免在循环体中使用远程过程调用。
如果可能的话尽可能使用AJAX方式的远程过程调用(异步方式的远程过程调用)。
避免将重量级的数据操作放置在客户端。例如:大批量的数据复制操作、需要通过大量的数据遍历完成的计算等。
改进对DOM对象的操作方式。
客户端的编程中,对DOM对象的操作往往是最容易占用CPU时间的。而对于DOM对象的操作,不同的编程方法之间的性能差异又往往是非常大的。
以下是三段运行结果完全相同的代码,它们的作用是在网页中创建一个10x1000的表格。然而它们的运行速度却有着天壤之别。
/* 测试代码1 - 耗时: 41秒*/
var table = document.createElement("TABLE");document.body.appendChild(table);for(var i = 0; i < 1000; i++){ var row = table.insertRow(-1); for(var j = 0; j < 10; j++){ var cell = objRow.insertCell(-1); cell.innerText = "( " + i + " , " + j + " )"; }}/* 测试代码2 - 耗时: 7.6秒 */var table = document.getElementById("TABLE");document.body.appendChild(table);var tbody = document.createElement("TBODY");table.appendChild(tbody);for(var i = 0; i < 1000; i++){ var row = document.createElement("TR"); tbody.appendChild(row); for(var j = 0; j < 10; j++){ var cell = document.createElement("TD"); row.appendChild(cell); cell.innerText = "( " + i + " , " + j + " )"; }}/* 测试代码3 - 耗时: 1.26秒 */var tbody = document.createElement("TBODY");for(var i = 0; i < 1000; i++){ var row = document.createElement("TR");for(var j = 0; j < 10; j++){ var cell = document.createElement("TD"); cell.innerText = "( " + i + " , " + j + " )"; row.appendChild(cell); } tbody.appendChild(row);}var table = document.getElementById("TABLE");table.appendChild(tbody); document.body.appendChild(table);var str = "";for (var i = 0; i < 50000; i++) {str += "xxxxxx";}这段代码耗时14.325秒,结果并不理想。现在我们将代码改为如下的形式:/* 测试代码2 - 耗时: 0.359秒 */var str = "";for (var i = 0; i < 100; i++) {var sub = "";for (var j = 0; j < 500; j++) {sub += "xxxxxx";}str += sub;}这段代码耗时0.359秒!同样的结果,我们做的只是首先拼装一些较小的字符串然后再组装成更大的字符串。这种做法可以有效的在字符串拼装的后期减小内存复制的数据量。知道了这一原理之后我们还可以把上面的代码进一步拆散以后进行测试。下面的代码仅耗时0.140秒。/* 测试代码3 - 耗时: 0.140秒 */var str = "";for (var i1 = 0; i1 < 5; i1++) {var str1 = "";for (var i2 = 0; i2 < 10; i2++) {var str2 = "";for (var i3 = 0; i3 < 10; i3++) {var str3 = "";for (var i4 = 0; i4 < 10; i4++) {var str4 = "";for (var i5 = 0; i5 < 10; i5++) {str4 += "xxxxxx";}str3 += str4;}str2 += str3;}str1 += str2;}str += str1;}不过,上面这种做法也许并不是最好的!如果我们需要提交的信息是XML格式的(其实绝大多数情况下,我们都可以设法将要提交的信息组装成XML格式),我们还能找到更高效更优雅的方法—利用DOM对象为我们组装字符串。下面这段代买组装一个长度为950015的字符串仅须耗时0.890秒。/* 利用DOM对象组装信息 - 耗时: 0.890秒 */var xmlDoc;if (browserType == BROWSER_IE) {xmlDoc = new ActiveXObject("Msxml.DOMDocument");}else {xmlDoc = document.createElement("DOM");}var root = xmlDoc.createElement("root");for (var i = 0; i < 50000; i++) {var node = xmlDoc.createElement("data");if (browserType == BROWSER_IE) {node.text = "xxxxxx";}else {node.innerText = "xxxxxx";}root.appendChild(node);}xmlDoc.appendChild(root);var str;if (browserType == BROWSER_IE) {str = xmlDoc.xml;}else {str = xmlDoc.innerHTML;}private static String getGZIPEncoding(HttpServletRequest request) { String acceptEncoding = request.getHeader("Accept-Encoding"); if (acceptEncoding == null) return null; acceptEncoding = acceptEncoding.toLowerCase(); if (acceptEncoding.indexOf("x-gzip") >= 0) return "x-gzip"; if (acceptEncoding.indexOf("gzip") >= 0) return "gzip"; return null;}