在实际的应用中我们经常希望开始多个线程。比如从一个表中得到一个数据集,经过各种计算,最后得到一个图表。你希望在这个过程中页面仍然能够得到正常的响应,这就需要用到后台处理技术。下面是自己总结的一个实例,可以参考一下。
Html代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
! Excerpted from "Pragmatic Guide to JavaScript",
! published by The Pragmatic Bookshelf.
! Copyrights apply to this code. It may not be used to create training material,
! courses, books, articles, and the like. Contact us if you are in doubt.
! We make no guarantees that this code is fit for any purpose.
! Visit http://www.pragmaticprogrammer.com/titles/pg_js for more book information.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="../prototype.js"></script>
<script type="text/javascript" src="background.js"></script>
<title>Simulating background processing - Pocket JavaScript</title>
<style type="text/css">
#progress {
border: 2px solid gray; text-align: center;
background: white; color: black; position: relative; width: 30em;
font-family: sans-serif;
}
#progress.over50 { color: white; }
#progress .visual {
position: absolute; left: 0; top: 0; height: 100%; width: 0;
background: green; z-index: 1;
}
#progress .figure { position: relative; z-index: 2; font-weight: bold; }
</style>
</head>
<body>
<h1>Simulating background processing</h1>
<p id="progress">
<span class="visual"></span>
<span class="figure">0%</span>
</p>
<p>
<input type="button" id="btnToggle" value="Toggle" />
<input type="button" id="btnOtherTask" value="Do some other stuff" />
</p>
</body>
</html>
Js代码
/***
* Excerpted from "Pragmatic Guide to JavaScript",
* published by The Pragmatic Bookshelf.
* Copyrights apply to this code. It may not be used to create training material,
* courses, books, articles, and the like. Contact us if you are in doubt.
* We make no guarantees that this code is fit for any purpose.
* Visit http://www.pragmaticprogrammer.com/titles/pg_js for more book information.
***/
(function() {
var CHUNK_INTERVAL = 25; // ms.单位为毫秒
var running = false, progress = 0, processTimer;
function runChunk() {
window.clearTimeout(processTimer);
processTimer = null;
if (!running) return;
// Some work chunk. Let's simulate it: 模拟任务的各个步骤
for (var i = 0; i < 10000; i += (Math.random() * 5).round())
;
++progress;
updateUI(); // See source archive -- just updates a progressbar 用来更新一个进度条
if (progress < 100) {
processTimer = window.setTimeout(runChunk, CHUNK_INTERVAL);
} else {
progress = 0, running = false;
}
}
function toggleProcessing() {
running = !running;
if (running) {
processTimer = window.setTimeout(runChunk, CHUNK_INTERVAL);
}
}
var progressbar, visual, figure;
function updateUI() {
visual.setStyle('width: ' + progress + '%;');
progressbar[progress < 50 ? 'removeClassName' : 'addClassName']('over50');
figure.update(progress + '%');
}
document.observe('dom:loaded', function() {
$('btnToggle').observe('click', toggleProcessing);
$('btnOtherTask').observe('click', function() {
$$('h1').first().insert(', yeah');
});
progressbar = $('progress');
visual = progressbar.down('.visual');
figure = progressbar.down('.figure');
});
})();
总结:
技巧的思路是把一个大型任务分解成若干个步骤,然后一边执行这些步骤,一边记录任务的进度,并在固定的时延对这些步骤进行调度。经过一段时间在执行下一个步骤,这段空闲时间里,浏览器会恢复对页面的控制,因此就可以正常地处理页面行为,并运行其他待执行脚本。