有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。


当前回答

在Firebug(可能还有其他JavaScript控制台)中,只有在指定的睡眠时间(…)之后,点击enter后才会发生任何事情

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}

使用示例:

函数sleepFor(sleepDuration){var now=new Date().getTime();而(newDate().getTime()<now+sleepDuration){/*什么都不做*/}}函数sleepThenAt(){sleepFor(2000);console.log(“您好,JavaScript睡眠!”);}sleepThenAt()

注:仅用于调试和开发

其他回答

出于对$DEITY的热爱,请不要使用忙等待睡眠功能。setTimeout和setInterval可以满足您的需要。

var showHide=document.getElementById('showHide');setInterval(()=>{showHide.style.visibility=“初始”;setTimeout(()=>{showHide.style.visibility=“隐藏”}, 1000);}, 2000); <div id=“showHide”>您好!再见</分区>

每隔两秒隐藏文本一秒。这显示了如何使用setInterval和setTimeout每秒显示和隐藏文本。

使用三种功能:

调用setInterval启动循环的函数一个函数,它调用clearInterval来停止循环,然后调用setTimeout来休眠,最后在setTimeout内调用作为回调来重新启动循环一个循环,跟踪迭代次数,设置睡眠次数和最大次数,一旦达到睡眠次数就调用睡眠函数,并在达到最大次数后调用clearInterval

var foo={};函数main(){“使用严格”;/*初始化全局状态*/foo.bar=foo.bar ||0;/*初始化计时器*/foo.bop=设置间隔(foo.baz,1000);}睡眠=功能(计时器){“使用严格”;clearInterval(计时器);timer=setTimeout(function(){main()},5000);};foo.baz=函数(){“使用严格”;/*更新状态*/foo.bar=数字(foo.bar+1)||0;/*日志状态*/console.log(foo.bar);/*检查状态并在10时停止*/(foo.bar===5)&&睡眠(foo.bop);(foo.bar==10)&&clearInterval(foo.bop);};main();

工具书类

使用JavaScript开发游戏为什么iOS 8中的滚动事件更改是一件大事Ember.js中的实时轮询系统使用requestAnimationFrame()驱动动画MDN:JavaScript并发模型和事件循环网格研究:Node.js在JavaScript中超过60fps第2部分:不阻塞单个线程的CPU密集型JavaScript计算

简短的答案是否定的,而不是JavaScript本身。您的解决方案似乎是不让控制权回归环境的唯一途径。

如果环境不支持事件,这是必要的。他们可能也不支持setTimeout。

如果您处于事件驱动环境(如浏览器或Node.js)中,setTimeout绝对是最好的方法。

2009年的一个老问题。2015年,ECMAScript 2015 AKA ES6中定义的生成器可以提供新的解决方案。它于2015年6月获得批准,但之前已在Firefox和Chrome中实现。现在,休眠功能可以在不冻结浏览器的情况下,在循环和子函数中进行非繁忙、非阻塞和嵌套。只需要纯JavaScript,不需要库或框架。

下面的程序显示了sleep()和runSleepyTask()是如何实现的。sleep()函数只是一个yield语句。它非常简单,实际上直接编写yield语句比调用sleep()更容易,但这样就不会有sleep单词了:-)yield返回一个时间值给wakeup()内的next()方法并等待。实际的“睡眠”是使用旧的setTimeout()在wakeup()中完成的。在回调时,next()方法触发yield语句继续,yield的“魔力”在于所有局部变量及其周围的整个调用堆栈仍然完好无损。

使用sleep()或yield的函数必须定义为生成器。这很容易通过在关键字函数*中添加星号来实现。执行生成器有点棘手。当使用关键字new调用时,生成器返回一个具有next()方法的对象,但不执行生成器的主体(关键字new是可选的,没有任何区别)。next()方法触发生成器主体的执行,直到遇到产量。包装函数runSleepyTask()启动乒乓球:next()等待yield,yield等待next(()。

另一种调用生成器的方法是使用关键字yield*,这里它的工作方式类似于一个简单的函数调用,但它还包括返回next()的能力。

示例drawTree()演示了这一切。它在旋转的3D场景上绘制了一棵带有树叶的树。一棵树被画成树干,顶部有三个不同方向的部分。在短暂的睡眠后,通过递归调用drawTree(),将每个部分绘制为另一个较小的树。一棵很小的树被画成一片叶子。

每个叶子在一个单独的任务中都有自己的生命,该任务以runSleepyTask()开始。它在growtLeaf()中出生、生长、静止、褪色、坠落和死亡。速度由sleep()控制。这证明了多任务处理是多么容易。

函数*sleep(毫秒){yield毫秒};函数runSleepyTask(任务){(函数唤醒(){var result=task.next();if(!result.done)setTimeout(唤醒,result.value);})()}////////////////作者:Ole Middelboe/////////////////////////////pen3D=setup3D();var taskObject=新绘图树(pen3D.center,5);runSleepyTask(taskObject);函数*drawTree(root3D,大小){如果(size<2)运行SleepyTask(new-growLeaf(root3D))其他{pen3D.drawTrunk(root3D,大小);for(变量p为[1,3,5]){var part3D=新pen3D.Thing;root3D.add(part3D);part3D.移动(尺寸).转动(p).倾斜(1-p/20);产量*睡眠(50);产量*drawTree(part3D,(0.7+p/40)*尺寸);}}}函数*growtLeaf(stem3D){var leaf3D=pen3D.drawLeaf(stem3D);对于(var s=0;s++<15;){yield*sleep(100);leaf3D.scale.multiplyScalar(1.1)}yield*sleep(1000+9000*Math.random());对于(var c=0;c++<30;){yield*sleep(200);leaf3D.sskin.color.setRGB(c/30,1-c/40,0)}对于(var m=0;m++<90;){yield*sleep(50);leaf3D.turn(0.4).tilt(0.3).move(2)}leaf3D.visible=false;}///////////////////////////////////////////////////////////////////////函数setup3D(){var场景,相机,渲染器,directionalLight,pen3D;scene=新的THREE.scene();相机=新的三个透视相机(75,window.innerWidth/window.innerHeight,0.1,1000);相机位置设置(0,15,20);renderer=new THREE.WebGLRenderer({alpha:真,抗锯齿:真});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(render.domElement);directionalLight=新的三个。directionalLight(0xffffaa,0.7);directionalLight.position.set(-1,2,1);scene.add(directionalLight);scene.add(新的THREE.AmbientLight(0x9999ff));(函数render(){requestAnimationFrame(渲染);//renderer.setSize(window.innerWidth,window.innerHeight);场景旋转Y(10/60/60);renderer.render(场景,摄影机);})();window.addEventListener窗口('调整大小',函数(){renderer.setSize(window.innerWidth,window.innerHeight);camera.aspx ect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();},假的);pen3D={drawTrunk:函数(根,大小){//root.skin=皮肤(0.5、0.3、0.2);root.add(新的三个网格(新的三维圆柱体几何体(大小/12,大小/10,大小16),root.skin).translateY(大小/2));root.add(新的THREE.Mesh(新的THEREE.SphereGeometry(size/12,16),root.skin).translateY(大小));返回根;},drawLeaf:功能(茎){stem.skin.color.setRGB(0,1,0);stem.add(新的三个网格(新的三维圆柱体几何体(0,0.02,0.6),茎.皮肤).旋转X(0.3).平移Y(0.3));stem.add(新的THREE.Mesh(新的THREE.CircleGeometry(0.2),茎.皮肤).旋转X(0.3).平移Y(0.4));返回阀杆;},事物:函数(){三.Object3D.调用(this);this.skin=新的THREE.MeshLambertMaterial({颜色:新三。颜色(0.5,0.3,0.2),vertexColors:THREE.FaceColors(顶点颜色),边:三边,双面})}};pen3D.Thing.prototype=对象创建(THREE.Object3D.prototype);pen3D.Thing.prototype.tilt=pen3D.Thing.prototype.rotateX;pen3D.Thing.prototype.turn=pen3D.Thing.prototype.rotateY;pen3D.Thing.prototype.move=pen3D.Thing.prototype.translateY;pen3D.center=新pen3D.Thing;scene.add(pen3D.center);返回pen3D;}<script src=“https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js“></script>

3D内容隐藏在setup3D()中,只是为了让它比console.log()少一些无聊。顺便说一下,角度是用弧度来测量的。

经测试可在Firefox和Chrome中运行。未在Internet Explorer和iOS(iPad)中实施。试着自己运行它。

在我再次找到答案后,加布里埃尔·拉特纳一年前对sleep()的JavaScript版本是什么做出了类似的回答?。

我使用多线程HTML5 Worker,它将能够中止指向无响应URL的同步XMLHttpRequest。这不会阻止浏览器。

https://gist.github.com/el-gringo/6990785