做firefox的开心网插件碰到个问题,想在偷菜时候sleep几秒,模拟人工操作,免得被服务器认为是外挂。但是javascript没有sleep这个函数,需要手工模拟实现。

在网上找了一下,基本有以下两种方案:

  1. 循环判断时间,满足条件则跳出循环

<pre class=”javascript” name=code>function sleep(n){ var start=new Date().getTime(); while(true) if(new Date().getTime()-start>n) break; }</pre> 由于循环判断很占用CPU,甚至会导致浏览器崩溃,所以这里又有人提出了用xmlhttprequest的同步调用,来实现sleep的功能,我试了一下CPU占用率还是挺高,效果不太理想。 <pre class=”javascript” name=code>function sleep(num){ var tempDate=new Date(); var theXmlHttp=ActiveXObject(“Microsoft.XMLHTTP”); while((new Date()-tempDate)< num){ try{ theXmlHttp.open(“get”,”http://www.google.com/JK.asp?JK=”+Math.random(),false); theXmlHttp.send(); } catch(e){;} } return; }</pre>

  1. 使用setTimeout函数模拟,可以几乎不占用CPU

<pre class=”javascript” name=code>function Sleep(obj,iMinSecond){ if (window.eventList==null) window.eventList=new Array(); var ind=-1; for (var i=0;i< window.eventList.length;i++){ if (window.eventList[i]==null){ window.eventList[i]=obj; ind=i; break; } } if (ind==-1){ ind=window.eventList.length; window.eventList[ind]=obj; } setTimeout(“GoOn(“ + ind + “)”,iMinSecond); } function GoOn(ind){ var obj=window.eventList[ind]; window.eventList[ind]=null; if (obj.NextStep) obj.NextStep(); else obj(); }

function Test(){ for(var i=0;i<10;i++){ Sleep(this,i*3000); this.NextStep=function() { alert(“continue”+i); } } }</pre>
但是使用setTimeout存在一个问题,就是无法动态的实现sleep功能。如上面的Test()函数,我们预期的效果是得到从0到9的是个数字,但实际的运行结果是10个10;猜想这是由于Javascript解释器在解释完所有脚本之后才开始执行alert函数,这时i的值已经变成10了。

还没想到好的sleep方法,开心农场的插件开发推迟中。


Simon Lee

My blog