【优化】分时加载
2010-03-16 11:55 BlueDream 阅读(1394) 评论(0) 编辑 收藏 举报分时加载的目的: 在用户体验的极限值去分批加载大型数据.保证浏览器整个数据加载的流畅.避免假死现象.
几点说明:
- timedChunk 函数,里面的 50ms 来自 Response Time Overview 中的调查结果:100ms 内的响应能让用户感觉非常流畅。50ms 是 Nicholas 针对 JavaScript 得出的最佳经验值。
- setTimeout 延时 25ms, 是因为浏览器的时间分辨率问题。25ms 可以保证主流浏览器都顺畅(有喘息的机会去更新 UI)。
- 上面的实例,传统方式加载会让浏览器在加载数据期间,无法更新界面和响应任何操作。采用分时加载,则可以让浏览器始终保持可响应状态,提升界面流畅性和用户体验。
以5000条表格数据为例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title> 分时加载 </title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style> button { width:200px; height:50px; } #lay {margin:0 auto; width: 670px; } #userlist { width:502px; border:1px solid #8C8C8C; margin-left:50px; margin-top:10px; height:30px; border-collapse:collapse; font-size:12px; } #userlist thead td { height:25px; border:1px solid #8C8C8C; text-align:center; background-color:#00CC00; } #userlist tbody td { height:25px; border:1px solid #8C8C8C; text-align:center; } </style> </head> <body> <div id="lay"> <button id="resetBtn">重置</button> <button id="tradBtn">传统加载</button> <button id="timeBtn">分时加载</button> <div style="width:500px; border:1px solid #000; background-color:#FFF; margin-left:50px; margin-top:10px; "> <div id="processBar" style="width:0; height:35px; background-color:#003366; line-height:35px; color:#FFF; "></div> </div> <table id="userlist"> <thead><tr><td>用户列表</td></tr></thead> <tbody></tbody> </table> </div> <script> var loadDemo = function() { var $ = function(id) { return document.getElementById(id); }, resetBtn = $('resetBtn'), tradBtn = $('tradBtn'), timeBtn = $('timeBtn'),progress = $('processBar'), userlist = $('userlist'), tbody = userlist.tBodies[0], i, n = 1, JSON_DATA = []; // 创建用户列表 function addItem(data) { var tr = document.createElement('tr'); var td = document.createElement('td'); td.appendChild(document.createTextNode(data[0])); tr.appendChild(td); tbody.appendChild(tr); if(++n % 10 == 0) progressing(); } // 加载进度 function progressing() { progress.style.width = (progress.offsetWidth + 1) + 'px'; } // 清空用户列表 function reset() { resetBtn.disabled = true; tradBtn.disabled = false; timeBtn.disabled = false; if(window.ActiveXObject) { // IE var temp = document.createElement('div'); temp.innerHTML = '<table><tbody></tbody></table>'; userlist.replaceChild(temp.firstChild.tBodies[0], tbody); tbody = userlist.tBodies[0]; } else { tbody.innerHTML = ''; } progress.innerHTML = ''; progress.style.width = 0; n = 1; } // 分时函数[*****] function timedChunk(items, process, context, callback) { var todo = items.concat(), delay = 25; setTimeout(function() { var start = +new Date(); do { process.call(context, todo.shift()); } while (todo.length > 0 && (+new Date() - start < 50)) if(todo.length > 0) { setTimeout(arguments.callee, 25); } else if(callback) { callback(); } }, delay); } // 分时加载 function testTimed() { resetBtn.disabled = true; tradBtn.disabled = true; timeBtn.disabled = true; var start = +new Date(), end; timedChunk(JSON_DATA, addItem, null, function() { resetBtn.disabled = false; end = +new Date(); progress.innerHTML = (end - start) + ' ms'; }); } // 传统加载 function testTrad() { resetBtn.disabled = true; tradBtn.disabled = true; timeBtn.disabled = true; var start = +new Date(), end; for(var i = 0, len = JSON_DATA.length; i < len; i++) { addItem(JSON_DATA[i]); } end = +new Date(); resetBtn.disabled = false; progress.innerHTML = (end - start) + ' ms'; } return { run: function() { // 模拟用户数据 for(i = 1; i <= 5000; i++) { JSON_DATA.push(['用户名称' + i]); } resetBtn.onclick = function() { reset(); } tradBtn.onclick = function() { testTrad(); } timeBtn.onclick = function() { testTimed(); } } } }(); loadDemo.run(); </script> </body> </html>
参考:
http://www.nczonline.net/blog/2009/08/11/timed-array-processing-in-javascript/