复制代码 代码如下: image A onload执行次数:<span id="ThreadA">0</span><br> image B onload执行次数:<span id="ThreadB">0</span><br> image C onload执行次数:<span id="ThreadC">0</span> <script> function Img(threadID,src) { var img = new Image; img.onload = function() { var c = parseInt(document.getElementById(threadID).innerHTML); document.getElementById(threadID).innerHTML=isNaN(c)?1:++c; } img.src = src; return img; }
var imgA = new Img("ThreadA","attachment/1178365293_0.gif"); var imgB = new Img("ThreadB","attachment/1178365293_1.gif"); var imgC = new Img("ThreadC","attachment/1178365293_2.gif"); </script>
是不是有点意思了? 再看下面的代码:
复制代码 代码如下: <script> //by Rimifon var Threads = new Array; onload = function() { for(var C=1;C<501;C++) { Threads.push(new Thread(C)); } } function Go(sender) { var IsStart = sender.value=="全部开始"; for(var x in Threads) { Threads[x].Start = IsStart; } sender.value = "全部" + (IsStart?"暂停":"开始"); } function Thread(ID) { this.Start = 0; var cursor = this; var span = document.createElement("span"); var counter = document.createTextNode("0"); span.appendChild(counter); var div = document.createElement("div"); div.appendChild(document.createTextNode("线程" + ID + ":")); div.style.cursor = "pointer"; div.onclick = function() { cursor.Start = !cursor.Start; } div.oncontextmenu = function() { img.onload = null; this.removeNode(true); return false; } div.appendChild(span); document.body.appendChild(div); var img = new Image; img.onload = function() { if(cursor.Start) counter.data = parseInt(counter.data) + 1; div.style.backgroundColor = cursor.Start?"#abcdef":"yellow"; } img.src = "images/51js.gif"; } </script> <input type=button value="全部开始" onclick="Go(this)"> <input type=button value="弹出对话框" onclick="alert("对话框测试")">
复制代码 代码如下: function ( id ) { var a = getArticle(id); document.writeln(a.name + "" + a.content); }
然而你也许会注意到,重复用同一个文章ID调用此函数,需要与服务器之间进行反复且无益的通信。想要解决这个问题,可以考虑使用函数 getArticleWithCache(),它相当于一个带有缓存能力的getArticle()。在这个例子中,getArticle()返回的数据只是作为一个全局变量被保存下来: 复制代码 代码如下: var cache = {}; function getArticleWithCache ( id ) { if ( !cache[id] ) { cache[id] = getArticle(id); } return cache[id]; }
现在已将读入的文章缓存起来,让我们再来考虑一下函数backgroundLoad(),它应用我们上面提到的缓存机制加载所有文章信息。其用途是,当读者在阅读某篇文章时,从后台预加载它所有子文章。因为文章数据是树状结构的,所以很容易写一个递归的算法来遍历树并且加载所有的文章: 复制代码 代码如下: function backgroundLoad ( ids ) { for ( var i=0; i < ids.length; i++ ) { var a = getArticleWithCache(ids[i]); backgroundLoad(a.children); } }
试试多线程编程 让我来介绍一下Concurrent.Thread,它是一个允许JavaScript进行多线程编程的库,应用它可以大大缓解上文提及的在AJAX开发中与异步通信相关的困难。这是一个用JavaScript写成的免费的软件库,使用它的前提是遵守Mozilla Public License和GNU General Public License这两个协议。你可以从他们的网站 下载源代码。
马上来下载和使用源码吧!假定你已经将下载的源码保存到一个名为Concurrent.Thread.js的文件夹里,在进行任何操作之前,先运行如下程序,这是一个很简单的功能实现: 复制代码 代码如下: <script type="text/javascript" src="Concurrent.Thread.js"></script> <script type="text/javascript"> Concurrent.Thread.create(function(){ var i = 0; while ( 1 ) { document.body.innerHTML += i++ + "<br>"; } }); </script>
执行这个程序将会顺序显示从0开始的数字,它们一个接一个出现,你可以滚屏来看它。现在让我们来仔细研究一下代码,他应用while(1)条件制造了一个不会中止的循环,通常情况下,象这样不断使用一个并且是唯一一个线程的JavaScript程序会导致浏览器看起来象冻结了一样,自然也就不会允许你滚屏。那么为什么上面的这段程序允许你这么做呢?关键之处在于while(1)上面的那条Concurrent.Thread.create()语句,这是这个库提供的一个方法,它可以创建一个新线程。被当做参数传入的函数在这个新线程里执行,让我们对程序做如下微调: 复制代码 代码如下: <script type="text/javascript" src="Concurrent.Thread.js"></script> <script type="text/javascript"> function f ( i ){ while ( 1 ) { document.body.innerHTML += i++ + "<br>"; } } Concurrent.Thread.create(f, 0); Concurrent.Thread.create(f, 100000); </script>