在javascript中用command模式模拟多线程
以前也看过有高手在wsh上可以创建thread对象,但是毕竟不是常规手段,我们做web应用一般没有本地访问权限的,用activex的没试过,毕竟也不是javascript方式。
以前我们解决这样的问题都是针对具体问题写一段代码来模拟多线程的,但是由于往往要对没个线程单独编码,这样的代码十分冗长(http://www.blogjava.net/Files/emu/counting.zip)。学习设计模式的时候就曾经考虑过在javascript中实用command模式来更好的模拟多线程,但是一直没有付诸实施,今天既然想起来了就试试看:
<html>
<head>
<title>emu -- 用command模式模拟多线程</title>
</head>
<body>
<SCRIPT LANGUAGE="JavaScript">
<!--
var commandList = [];
function executeCommands(){
if (commandList.length>0){
commandList.shift()();
}
}
function startNewTask(){
var resultTemp = document.createElement("span");
document.body.insertBefore(resultTemp,document.body.lastChild);
document.body.insertBefore(document.createElement("br"),document.body.lastChild);
resultTemp.innerText = 0;
commandList.push(function(){simThread(resultTemp,0);});
}
function simThread(temp,n){
temp.innerText = temp.innerText-(-n);
if (n<1000)
commandList.push(function(){simThread(temp,++n);});
else{
document.body.removeChild(temp.nextSibling);
document.body.removeChild(temp);
}
}
window.onload = function(){setInterval("executeCommands()",1);}
//-->
</SCRIPT>
<button onclick="startNewTask()">start</button>
<BR><BR>
</body>
</html>
注意第11行。javascript里面函数也是对象,所以就没有必要把函数调用包装到do或者execute方法里面了,直接用()就可以让函数对象运行起来:
commandList.shift()();
shift函数是javascript中array对象的函数,可是IE5居然没有定义,不过我曾经实现过IE5上面没实现的全部array函数,可以用这个脚本来增强IE5: http://www.blogjava.net/Files/emu/IE5ArrayFunctions.zip
问题点数:200、回复次数:67Top
1 楼ttyp(@http://www.cnblogs.com/ttyp/)回复于 2005-06-08 21:13:12 得分 1
不错!!Top
2 楼cslren(位流)回复于 2005-06-08 21:22:39 得分 1
支持你Top
3 楼fason(咖啡人生)回复于 2005-06-08 22:21:38 得分 1
:_)Top
4 楼leojay1(绯村剑心)回复于 2005-06-08 23:06:51 得分 1
markTop
5 楼emu_ston(祝福后山)回复于 2005-06-09 09:18:14 得分 0
改进了一下,现在允许在一个运行周期里面运行多个command,同时提供了对线程延迟的支持(见executeCommands函数中)。任务是计算1+2+3...+1000累加的结果。现在让每个任务运行完成后延迟2秒再清楚自己的运行结果。点击一次鼠标就建立一个线程。
<html>
<head>
<title>emu -- 用command模式模拟多线程</title>
</head>
<body>
<SCRIPT LANGUAGE="JavaScript">
<!--
if (Array.prototype.shift==null)
Array.prototype.shift = function (){
var rs = this[0];
for (var i=1;i<this.length;i++) this[i-1]=this[i]
this.length=this.length-1
return rs;
}
if (Array.prototype.push==null)
Array.prototype.push = function (){
for (var i=0;i<arguments.length;i++) this[this.length]=arguments[i];
return this.length;
}
var commandList = [];
var nAction = 0;//控制每次运行多少个动作
var functionConstructor = function(){}.constructor;
function executeCommands(){
for (var i=0;i<nAction;i++)
if (commandList.length>0){
var command = commandList.shift();
if (command.constructor == functionConstructor)
if (command.scheduleTime == null || new Date()-command.scheduleTime>0)
command();
else
commandList.push(command);
}
}
function startNewTask(){
var resultTemp = document.getElementById("sampleResult").cloneNode(true);
with (resultTemp){
id="";style.display="block";style.color=Math.random()*(2<<23.5);
}
document.body.insertBefore(resultTemp,document.body.lastChild);
commandList.push(function(){simThread(resultTemp,1);});
nAction++;
}
function simThread(temp,n){
if (temp.stop) n--;
else temp.innerText = temp.innerText-(-n);
if (n<1000)
commandList.push(function(){simThread(temp,++n)});
else{
var command = function(){document.body.removeChild(temp);;nAction--;};
command.scheduleTime = new Date()-(-2000);
commandList.push(command);
}
}
window.onload = function(){setInterval("executeCommands()",1);}
//-->
</SCRIPT>
<button onclick="startNewTask()">开始新线程</button>
<BR><BR>
<div id=sampleResult onmouseover="this.stop=true" onmouseout="this.stop=false" style="display:none;cursor:hand">0</div>
</body>
</html>
看了一下cpu占用,开1个任务和10个任务的cpu占用基本上没有区别。其实真正用在任务上的cpu时间是很少的。Top
6 楼emu_ston(祝福后山)回复于 2005-06-09 09:18:36 得分 0
改进了一下,现在允许在一个运行周期里面运行多个command,同时提供了对线程延迟的支持(见executeCommands函数中)。任务是计算1+2+3...+1000累加的结果。现在让每个任务运行完成后延迟2秒再清楚自己的运行结果。点击一次鼠标就建立一个线程。
<html>
<head>
<title>emu -- 用command模式模拟多线程</title>
</head>
<body>
<SCRIPT LANGUAGE="JavaScript">
<!--
if (Array.prototype.shift==null)
Array.prototype.shift = function (){
var rs = this[0];
for (var i=1;i<this.length;i++) this[i-1]=this[i]
this.length=this.length-1
return rs;
}
if (Array.prototype.push==null)
Array.prototype.push = function (){
for (var i=0;i<arguments.length;i++) this[this.length]=arguments[i];
return this.length;
}
var commandList = [];
var nAction = 0;//控制每次运行多少个动作
var functionConstructor = function(){}.constructor;
function executeCommands(){
for (var i=0;i<nAction;i++)
if (commandList.length>0){
var command = commandList.shift();
if (command.constructor == functionConstructor)
if (command.scheduleTime == null || new Date()-command.scheduleTime>0)
command();
else
commandList.push(command);
}
}
function startNewTask(){
var resultTemp = document.getElementById("sampleResult").cloneNode(true);
with (resultTemp){
id="";style.display="block";style.color=Math.random()*(2<<23.5);
}
document.body.insertBefore(resultTemp,document.body.lastChild);
commandList.push(function(){simThread(resultTemp,1);});
nAction++;
}
function simThread(temp,n){
if (temp.stop) n--;
else temp.innerText = temp.innerText-(-n);
if (n<1000)
commandList.push(function(){simThread(temp,++n)});
else{
var command = function(){document.body.removeChild(temp);;nAction--;};
command.scheduleTime = new Date()-(-2000);
commandList.push(command);
}
}
window.onload = function(){setInterval("executeCommands()",1);}
//-->
</SCRIPT>
<button onclick="startNewTask()">开始新线程</button>
<BR><BR>
<div id=sampleResult onmouseover="this.stop=true" onmouseout="this.stop=false" style="display:none;cursor:hand">0</div>
</body>
</html>
看了一下cpu占用,开1个任务和10个任务的cpu占用基本上没有区别。其实真正用在任务上的cpu时间是很少的。Top
7 楼DuJianDong(翼)回复于 2005-06-09 11:06:04 得分 1
markTop
8 楼emu_ston(祝福后山)回复于 2005-06-09 11:16:56 得分 0
改了一下,现在可以在firefox下面运行了:
<html>
<head>
<title>emu -- 用command模式模拟多线程</title>
</head>
<body>
<SCRIPT LANGUAGE="JavaScript">
<!--
if (Array.prototype.shift==null)
Array.prototype.shift = function (){
var rs = this[0];
for (var i=1;i<this.length;i++) this[i-1]=this[i]
this.length=this.length-1
return rs;
}
if (Array.prototype.push==null)
Array.prototype.push = function (){
for (var i=0;i<arguments.length;i++) this[this.length]=arguments[i];
return this.length;
}
var commandList = [];
var nAction = 0;//控制每次运行多少个动作
var functionConstructor = function(){}.constructor;
function executeCommands(){
for (var i=0;i<nAction;i++)
if (commandList.length>0){
var command = commandList.shift();
if (command.constructor == functionConstructor)
if (command.scheduleTime == null || new Date()-command.scheduleTime>0)
command();
else
commandList.push(command);
}
}
function startNewTask(){
var resultTemp = document.getElementById("sampleResult").cloneNode(true);
with (resultTemp){
id="";style.display="block";style.color=(Math.floor(Math.random()* (1<<23)).toString(16)+"00000").substring(0,6);
}
document.body.insertBefore(resultTemp,document.body.lastChild);
commandList.push(function(){simThread(resultTemp,1);});
nAction++;
}
function simThread(temp,n){
if (temp.stop) n--;
else temp.innerHTML = temp.innerHTML - (-n);
if (n<1000)
commandList.push(function(){simThread(temp,++n)});
else{
var command = function(){document.body.removeChild(temp);;nAction--;};
command.scheduleTime = new Date()-(-2000);
commandList.push(command);
}
}
window.onload = function(){setInterval("executeCommands()",1);}
//-->
</SCRIPT>
<button onclick="startNewTask()">开始新线程</button>
<BR><BR>
<div id=sampleResult onmouseover="this.stop=true" onmouseout="this.stop=false" style="display:none;cursor:hand">0</div>
</body>
</html>
主要是改了: else temp.innerHTML = temp.innerHTML - (-n);
和:style.color=(Math.floor(Math.random()* (1<<23)).toString(16)+"00000").substring(0,6);Top
9 楼meizz(梅花雪)回复于 2005-06-09 11:17:27 得分 20
emu 的东东必是精品, 支持地说Top
10 楼emu_ston(祝福后山)回复于 2005-06-09 13:37:55 得分 0
在firefox下面屏幕闪的很厉害,估计是firefox为了支持多平台没有调用directX写屏造成屏幕显示不流畅,有没有高手能解决这个问题呢?Top
11 楼ttyp(@http://www.cnblogs.com/ttyp/)回复于 2005-06-09 14:51:18 得分 10
屏幕显示就不要研究了,要研究研究线程的其他功能,如暂停,停止,重新开始,同步,信号等,并加以封装,呵呵Top
12 楼emu_ston(祝福后山)回复于 2005-06-09 15:12:51 得分 0
脚本语言而已啦,有必要做的那么复杂吗,主要是想在不失去响应的情况下提供一个后台运算的能力。Top
13 楼ttyp(@http://www.cnblogs.com/ttyp/)回复于 2005-06-09 15:19:57 得分 1
玩就玩个彻底了,至少你可以让多线程不止是运算,至少可以让调用更简单点吧。像JS做的星际里就有多线程的部分Top
14 楼runmin()回复于 2005-06-09 16:41:18 得分 1
活活,搅和一下Top
15 楼satans18((何畏)(只要你过得比我好))回复于 2005-06-09 17:26:29 得分 1
厉害~向高手学习!! :)Top
16 楼applebomb(袋装苹果)回复于 2005-06-09 18:06:29 得分 1
mark一下Top
17 楼ken2002(尖刀)回复于 2005-06-09 18:14:32 得分 1
收藏了Top
18 楼rightyeah(众妙之门)回复于 2005-06-10 08:22:00 得分 10
说白了就算多任务的队列化,想法不错,效果也还行,不过算不得厉害Top
19 楼patchclass(黑翼)回复于 2005-06-10 08:59:41 得分 1
markTop
20 楼s_phoenix()回复于 2005-06-10 09:00:25 得分 1
学习!Top
21 楼LGEN()回复于 2005-06-10 10:02:27 得分 0
呵呵程序太多,看不懂,能否说一下思想和原理。Top
22 楼LGEN()回复于 2005-06-10 10:10:52 得分 10
其实不能算是多线程,只是放一堆函数在数组里,然后一个一个执行而已。
如果你的每个执行的函数都是死循环,而你的程序能让它们都执行,这才是多线程初步。
Top
23 楼emu_ston(祝福后山)回复于 2005-06-10 10:10:57 得分 0
其实command模式只是用来模拟多线程而已,并不是真的实现了多线程,象暂停,重新开始,同步,信号这些当然也只能模拟实现。象我上面的代码看起来都可以暂停(鼠标指向一个任务的时候它就暂停运算了),重新开始(鼠标移开),schedule(一个任务结束后我安排它延迟两秒后把结果擦除)。
至于线程间的通讯和同步等高级功能,就算在java里面也不是那么简单的,君不见jdk每次升级往往都会在这方面做一些增强,网上杂志上讨论这个话题的文章也铺天盖地。用脚本来模拟这个东西一是做不好,二是实用性不强,做出来了多半也就是“玩的彻底”一点而已。Top
24 楼dh20156(风之石)回复于 2005-06-10 10:15:51 得分 1
学习,接分!Top
25 楼a040liutao(冬之心)回复于 2005-06-10 10:25:06 得分 0
顺便用多线程帮我解决这个问题吧,异步带回的HTML代码写到DIV中去 但两个函数同时执行时第一个会写不了,因为第2个没等第一个返回HTML代码就已经执行了就中断了第一个,代码如写
<script language="javascript">
/****************************************************************
* 函数名:fnDo
* 功能描述:向指定的DIV/SPAN中写入异步带回的HTML代码
* 输入:
* 版本:2005-05-27 by lt
/***************************************************************/
function fnDo(ID,sDiv,sUrl)
{
sDiv.innerHTML = "Loading..."
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
var xmlDom = new ActiveXObject("Msxml2.DOMDocument");
var strURL = sUrl + ID;
xmlhttp.Open("POST",strURL , true);
xmlhttp.onreadystatechange = function(){
var state = xmlhttp.readyState;
var xmlDom = new ActiveXObject("Msxml2.DOMDocument");
if (state == 4)
{
xmlDom.loadXML(xmlhttp.responseXML.xml);
//alert(xmlDom.documentElement.selectSingleNode("//objXML").text)
var getInfo = xmlDom.documentElement.selectSingleNode("//objXML").text;
sDiv.innerHTML = getInfo
}
};
xmlhttp.Send(xmlDom);
return 1;
}
//--------------------------------------------------------
</script>
<div id="divCategroy"></div>
<div id="divContent"></div>
<script language="javascript">
fnDo(0,divCategroy,"getcategory.asp?ID=")
fnDo(0,divContent,"getcategory.asp?ID=")
</script>
Top
26 楼JK_10000(JK)回复于 2005-06-10 10:46:10 得分 20
回复人: emu_ston(吃的就是没文化的亏) ( ) 信誉:127 2005-06-10 10:10:00 得分: 0
"其实command模式只是用来模拟多线程而已,并不是真的实现了多线程"
----
不少朋友喏喏称是,所以正在怀疑自己呢,
function simThread(temp,n){
在这一句后加了一句:
if(Math.random()>0.99) alert();
测试结果分明就是单线程啊
捊须深思中。。。。
Top
27 楼JK_10000(JK)回复于 2005-06-10 10:56:31 得分 20
虽说script本身不支持多线程
但是多个窗口里的script可以同时运行,也可以当多线程看,
还有window.showModelessDialog()它事实是也是多提供一个线程。
回复人: a040liutao(冬之心) ( ) 信誉:100 2005-06-10 10:25:00 得分: 0
的问题,可以参考:
http://jkisjk.vip.sina.com/html/getDataFromServer.htm 的第一种方式Top
28 楼patchclass(黑翼)回复于 2005-06-10 12:36:14 得分 10
好像可以利用iframe来模拟多线程的,学习楼主的办法Top
29 楼emu_ston(祝福后山)回复于 2005-06-10 13:40:43 得分 0
用iframe啊?倒没想过。Top
30 楼a040liutao(冬之心)回复于 2005-06-10 14:52:26 得分 1
JK_10000(JK) 你给的地址打不开Top
31 楼emu_ston(祝福后山)回复于 2005-06-13 18:53:47 得分 0
试验了一下,iframe只能用来建立新的变量命名空间,却没有办法创建互不干扰的进程,一个iframe里面在执行运算任务的时候,其他的框架和主框架全部都被堵塞住了,没有办法实现上面的功能:
<html>
<head>
<title></title>
</head>
<body>
<button onclick="newTask()">new task</button>
<SCRIPT LANGUAGE="JavaScript">
<!--
var framesCount = 0;
function newTask(){
var elm = document.createElement("iframe");
document.body.insertBefore(elm);
elm.style.display="none";
framesCount++;
document.frames[framesCount-1].document.write("<script>for (var i=0,n=0;i<=1000000;n+=i++);alert(n)<\/script>")
}
//-->
</SCRIPT>
</body>
</html>
点击按钮的时候开始执行运算,在运算结束前没有办法再点击一次按钮来开启一个新线程的。
modaldialog是肯定会堵塞主窗口的。开新窗口还有点用:
<html>
<head>
<title></title>
</head>
<body>
<SCRIPT LANGUAGE="JavaScript">
<!--
function newTask(left){
var win = window.open("","","top=300,height=100,status=yes,width=300,left="+left);
win.document.write("<script>setTimeout('for (var i=0,n=0;i<=10001;n+=i++)status=n;',1000)<\/script>")
}
newTask(0);
newTask(330);
newTask(660);
//-->
</SCRIPT>
</body>
</html>Top
32 楼emu_ston(祝福后山)回复于 2005-06-13 19:03:21 得分 0
演示iframe确实会相互堵塞的一个更好的例子:
<html>
<head>
<title></title>
</head>
<body>
<SCRIPT LANGUAGE="JavaScript">
<!--
var count1=0;
var count2=0;
var elm = document.createElement("iframe");
document.body.insertBefore(elm);
elm.style.display="none";
document.frames[0].document.write("<script>setTimeout(\"for (var i=0,n=0;i<=10001;n+=i++){parent.count1=n;parent.status=parent.count1+' - '+parent.count2};\",1000)<\/script>")
var elm = document.createElement("iframe");
document.body.insertBefore(elm);
elm.style.display="none";
document.frames[1].document.write("<script>setTimeout(\"for (var i=0,n=0;i<=10001;n+=i++){parent.count2=n;parent.status=parent.count1+' - '+parent.count2};\",1000)<\/script>")
//-->
</SCRIPT>
</body>
</html>Top
33 楼HLis(就是 HLis ~~)回复于 2005-06-13 22:47:25 得分 1
前些天不是有一个帖子介绍了基于 HTTP 的 QQ 协议吗,我按照这个写了一个 QQ 客户端,在 WSH 里啊,HTML 里啊都可以运行的。就因为只有一个线程头疼来着,Tencent 服务器现在太慢了,发一条消息会急死人的。
Emm... 先 Mark ,再仔细看看~~Top
34 楼JK_10000(JK)回复于 2005-06-14 11:54:33 得分 10
iframe确实会相互堵塞:
test.html-----------
<iframe src="a1.html" > </iframe>
<iframe src="a1.html" > </iframe>
a1.html------------
<script language=javascript >
alert();
</script>
两个alert不能同时出现,证明不是真正的多线程
Top
35 楼JK_10000(JK)回复于 2005-06-14 12:04:40 得分 10
用showModelessDialog来模拟多线程的不足是:没法把这个对话框移出视线外。
开多个窗口,让多个窗口里的script各自执行,来模拟多线程应该可行。
下例是非模态alert,也应该算是模拟多线程的一种应用:
http://jkisjk.vip.sina.com/html/closeAlertBox.htmTop
36 楼JK_10000(JK)回复于 2005-06-14 12:06:58 得分 0
回复人: a040liutao(冬之心) ( ) 信誉:100 2005-06-10 14:52:00 得分: 0
-----
可能是有时网络不好Top
37 楼BlueDestiny(Design Life - never-online.net)回复于 2005-06-14 14:24:35 得分 1
:)
做个记号。Top
38 楼emu_ston(祝福后山)回复于 2005-06-14 18:17:58 得分 0
jk:
showModelessDialog是我所知道的唯一能够堵塞正在运行的进程的方法,怎么可能用它来模拟多线程呢?你没有办法同时显示多个模式对话框,因为显示第一个的时候主页面的线程就停下来等了,一直到关掉它第二个才有可能打得开。
Top
39 楼emu_ston(祝福后山)回复于 2005-06-14 18:19:43 得分 0
哦看错了,我说的是modalDialog,你说的是showModelessDialog呵呵,全乱套了。Top
40 楼JK_10000(JK)回复于 2005-06-15 08:50:13 得分 10
http://jkisjk.vip.sina.com/html/closeAlertBox.htm
上面的非模态alert与自动关闭alert,
也应该算是模拟多线程的一种应用,可以同时弹出多个alert框
用的是showModelessDialog方式
因为当时看到有朋友发贴要求“自动关闭alert对话框”,
所以写了个来凑热闹,尽管没有实际用途。
----捊须而笑
Top
41 楼emu_ston(祝福后山)回复于 2005-06-15 13:46:53 得分 0
还“捊须”呢,留胡子啦?Top
42 楼JK_10000(JK)回复于 2005-06-15 16:20:59 得分 0
一颏红须招风戏
两鬓斑发任月窥
岁月不饶人啊Top
43 楼emu_ston(祝福后山)回复于 2005-06-15 18:20:32 得分 0
还吟诗?要我送你刮胡子刀就明说嘛。Top
44 楼JK_10000(JK)回复于 2005-06-16 09:09:33 得分 0
年纪到,容易生感慨
附庸下风雅,辱没次期文,
聊以自娱,料无大妨
刮胡子刀就免了,
这些事让我儿我女婿送就得,
不敢劳stone大驾。
捊须而笑--Top
45 楼fason(咖啡人生)回复于 2005-06-16 20:59:41 得分 10
onreadystatechange函数来处理回调的时候更象多线程的效果些Top
46 楼emu_ston(祝福后山)回复于 2005-06-17 10:43:23 得分 0
不明白你的意思。你是说window.open之后在新窗口的onreadystatechange里面回掉主页面吗?Top
47 楼yonghengdizhen(等季节一过,繁花就凋落)回复于 2005-06-17 11:22:05 得分 0
我想fason就是这个意思.不过解释执行的脚本程序不管如何模拟,离多线程还远着呢.
onreadystatechange我也试过,其中一个onreadystatechange执行阻塞,其余onreadystatechange永远都没机会执行.
可以这么测试一下:
用两个iframe加载两个htm,其中一个iframe的onreadystatechange中使用模式对话框
你会发现,先加载完成的页面显示模式对话框,在未被确认之前,第二个页面永远没有机会加载完成.Top
48 楼yonghengdizhen(等季节一过,繁花就凋落)回复于 2005-06-17 11:30:52 得分 0
sorry,看来我说错了,ie6看起来不一样Top
49 楼yonghengdizhen(等季节一过,繁花就凋落)回复于 2005-06-17 11:44:11 得分 10
不过如下的测试页面可以说明问题:
x.htm /*****直接在地址栏输入x.htm并回车,这时候你可能看不到两个alert同时出现的情况,并且在这种情况下,必须将该alert消息确认之后,两个文档才加载完成
<script>
function test()
{
var sDialogHW = "dialogWidth:350px; dialogHeight:250px;status:no;";
var sDialogULR = "about:blank";
retDlg=window.showModalDialog(sDialogULR,null,sDialogHW);
}
</script>
<iframe onreadystatechange="test()" src="y.htm"></iframe>
<iframe onreadystatechange="test()" src="z.htm"></iframe>
y.htm
<script>
alert(1)
</script>
<b>finish</b>
z.htm
<script>
alert(2)
</script>
<b>finish2</b>
Top
50 楼gu1dai(异域苍穹.百年飞行)回复于 2005-06-18 09:33:40 得分 1
挺好的Top
51 楼12345_(上山打老虎)回复于 2005-06-18 09:51:27 得分 1
咦!高手真xx多!:)Top
52 楼cuixiping(无心●愚公)回复于 2005-06-18 12:01:08 得分 10
这怎么多线程啊?
关键是 setInterval ,定时的去执行一个命令而已。Top
53 楼superdullwolf(超级大笨狼,每天要自强,MVP)回复于 2005-06-19 08:59:52 得分 1
只有2个CPU以上才是真正的多线程。Top
54 楼patchclass(黑翼)回复于 2005-06-19 09:59:38 得分 10
showModelessDialog 用来实现alert()自动关闭的方法不错哦,呵呵
这个帖子还真蛮热闹的
对于用alert判断是否多线程不大科学吧,alert我想在浏览器端就是 执行阻塞的,什么时候见过同时一个页面出现两个alert的呢?
继续讨论Top
55 楼ops2000(吾痴石)回复于 2005-06-19 12:15:05 得分 10
我同意 fason(咖啡人生) 的onreadystatechange函数来处理回调的时候更象多线程的效果些。楼主作为对多线程的探讨,我没有任何异议。但不同的模式它的应用领域是不一样的,好比j2ee有j2ee的模式,j2se有自己的模式。我以为command模式就不应该是网页开发的合适模式。而最好能用onreadystatechange这种异步回调模式。模式直接影响框架设计,如果一个网页用command模式去思考,那么到后来越来越困难,网页也是越写越复杂。而如果一开始就能用异步回调模式来思考框架,可能很多问题迎刃而解,甚至都不会出现了。现在流行的ajax,我看了一些老外的核心代码都用的onreadystatechange。
个人浅见,仁仁智智Top
56 楼emu_ston(祝福后山)回复于 2005-06-20 08:59:41 得分 0
唉,还是吃的没文化的亏,看不明白啊。比如说我一开始的例子,用onreadystatechange怎么模拟呢?Top
57 楼emu_ston(祝福后山)回复于 2005-06-20 10:30:25 得分 0
今天看到fason的http://community.csdn.net/Expert/TopicView.asp?id=3191873被翻出来了。fason的方法来模拟相同的效果显然更简洁:
<html><head><title>emu -- 用command模式模拟多线程</title></head><body>
<SCRIPT LANGUAGE="JavaScript">
<!--
var _st = window.setTimeout;
window.setTimeout = function(fRef, mDelay) {
if(typeof fRef == 'function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _st(f, mDelay);
}
return _st(fRef,mDelay);
}
var _int = window.setInterval;
window.setInterval = function(fRef, mDelay) {
if(typeof fRef == 'function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _int(f, mDelay);
}
return _st(fRef,mDelay);
}
function startNewTask(){
var target = document.getElementById("sampleResult").cloneNode(true);
with (target){
id="";style.display="block";style.color=(Math.floor(Math.random()* (1<<23)).toString(16)+"00000").substring(0,6);
}
document.body.insertBefore(target,document.body.lastChild);
var parameter = {target:target,n:0,result:0}
parameter.timer = setInterval(count,1,parameter);
}
function count(parameter){
with (parameter){
if (n<100){
if (!target.stop)result += ++n
target.innerHTML = result;
}else{
clearInterval(timer);
setTimeout(function(elm){document.body.removeChild(elm)},2000,target);
}
}
}
//-->
</SCRIPT>
<button onclick="startNewTask()">开始新线程</button>
<BR><BR>
<div id=sampleResult onmouseover="this.stop=true" onmouseout="this.stop=false" style="display:none;cursor:hand">0</div>
</body>
</html>
有的时候command模式也许不是最好的办法,比如我上面的例子。写上面的例子纯粹只是为了演示command确实可以用在javascript中,并不表示我们任何时候都应该优先考虑这样做。
至于command模式本身,我仍认为它是最简洁优美的模式之一,在我们用各种语言解决问题的时候都可以考虑使用它,而不止于j2se。
套一句名言:如果你的工具箱里面只有榔头这一样工具,那么每个问题在你的眼里看起来都象钉子。Top
58 楼emu_ston(祝福后山)回复于 2005-06-20 10:34:20 得分 0
上面的代码在firefox下面闪烁太厉害,改一下:
function count(parameter){
with (parameter){
if (n<1000){
if (!target.stop){
result += ++n;
target.innerHTML = result;
}
}else{
clearInterval(timer);
setTimeout(function(elm){document.body.removeChild(elm)},2000,target);
}
}
}
这种方式在firefox下面运行起来比在ie下面快,不大明白原因。Top
59 楼emu_ston(祝福后山)回复于 2005-06-20 10:52:03 得分 0
如果想要运算快一点,可以这样:
<html><head><title>emu -- 用fason的参数化定时器模拟多线程</title></head><body>
<SCRIPT LANGUAGE="JavaScript">
<!--
var _st = window.setTimeout;
window.setTimeout = function(fRef, mDelay) {
if(typeof fRef == 'function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _st(f, mDelay);
}
return _st(fRef,mDelay);
}
var _int = window.setInterval;
window.setInterval = function(fRef, mDelay) {
if(typeof fRef == 'function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _int(f, mDelay);
}
return _st(fRef,mDelay);
}
function startNewTask(){
var target = document.getElementById("sampleResult").cloneNode(true);
with (target){
id="";style.display="block";style.color=(Math.floor(Math.random()* (1<<23)).toString(16)+"00000").substring(0,6);
}
document.body.insertBefore(target,document.body.lastChild);
var parameter = {target:target,n:0,result:0}
parameter.timer = setInterval(count,1,parameter);
}
function count(parameter){
with (parameter){
if (!target.stop){
for(var i=0;i<speed;i++)
if (n<MAX) result += ++n;
target.innerHTML = result;
}
if (n>=MAX){
clearInterval(timer);
setTimeout(function(elm){document.body.removeChild(elm)},2000,target);
}
}
}
var speed = 1111;
var MAX=100000;
//-->
</SCRIPT>
<button onclick="startNewTask()">开始新线程</button>
<BR><BR>
<div id=sampleResult onmouseover="this.stop=true" onmouseout="this.stop=false" style="display:none;cursor:hand">0</div>
</body>
</html>
不过“线程”开多了或者加速太大了,就比较占cpu。Top
60 楼patchclass(黑翼)回复于 2005-06-20 11:34:56 得分 1
收藏,晚上回去 看看Top
61 楼zhiin(┈ Jcan ┈)回复于 2005-07-06 19:57:22 得分 0
强贴留名Top
62 楼wxylvmnn(城隍庙三当家的)回复于 2005-07-11 10:36:11 得分 0
某某路过此地。。。Top
63 楼777kit(型死)回复于 2005-07-21 15:48:34 得分 0
强贴留名
Top
64 楼mymmsc(热血老猫)回复于 2005-08-09 09:49:40 得分 0
太强了!Top
65 楼emu_ston(祝福后山)回复于 2005-08-11 14:09:04 得分 0
var _int = window.setInterval;
window.setInterval = function(fRef, mDelay) {
if(typeof fRef == 'function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _int(f, mDelay);
}
return _st(fRef,mDelay);
}
应为:
var _int = window.setInterval;
window.setInterval = function(fRef, mDelay) {
if(typeof fRef == 'function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _int(f, mDelay);
}
return _int(fRef,mDelay);
}Top
66 楼boyzhang(张郎)(爱你爱到Windows没BUG的那天)回复于 2005-08-21 17:48:19 得分 0
Mark一下!Top
67 楼hawk2004(漠沙飞-relearn)回复于 2005-08-30 14:20:29 得分 0
upTop




