有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
}
这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。
这可以使用Java的睡眠方法来完成。我已经在Firefox和Internet Explorer中测试过它,它不会锁定计算机,不会占用资源,也不会导致无休止的服务器攻击。对我来说,这似乎是一个干净的解决方案。
首先,您必须在页面上加载Java并使其方法可用。为了做到这一点,我这样做了:
<html>
<head>
<script type="text/javascript">
function load() {
var appletRef = document.getElementById("app");
window.java = appletRef.Packages.java;
} // endfunction
</script>
<body onLoad="load()">
<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />
然后,当您想要在JavaScript代码中轻松暂停时,您需要做的就是:
java.lang.Thread.sleep(xxx)
其中xxx是以毫秒为单位的时间。在我的案例中(作为理由),这是一家非常小的公司后端订单履行的一部分,我需要打印一张必须从服务器加载的发票。我是通过将发票(作为网页)加载到iFrame中,然后打印iFrame来完成的。
当然,我必须等到页面完全加载后才能打印,所以JavaScript代码必须暂停。我通过让发票页面(在iFrame中)使用onLoad事件更改父页面上的隐藏表单字段来实现这一点。打印发票的父页面上的代码如下(为清晰起见,将不相关的部分切割):
var isReady = eval('document.batchForm.ready');
isReady.value = 0;
frames['rpc_frame'].location.href = url;
while (isReady.value == 0) {
java.lang.Thread.sleep(250);
} // endwhile
window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();
因此,用户按下按钮,脚本加载发票页面,等待,每季度检查一次发票页面是否完成加载,并弹出打印对话框,供用户将其发送到打印机。QED。
我也遇到过类似的问题,必须等待控件的存在并每隔一段时间进行检查。由于JavaScript中没有真正的休眠、等待或暂停,并且Internet Explorer中不正确支持使用wait/async,因此我使用setTimeOut并注入函数以成功找到元素。以下是完整的示例代码,因此每个人都可以复制并将其用于自己的项目:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
var ElementSearchStatus = {
None: 0,
Found: 1,
NotFound: 2,
Timeout: 3
};
var maxTimeout = 5;
var timeoutMiliseconds = 1000;
function waitForElement(elementId, count, timeout, onSuccessFunction) {
++count;
var elementSearchStatus = existsElement(elementId, count, timeout);
if (elementSearchStatus == ElementSearchStatus.None) {
window.setTimeout(waitForElement, timeoutMiliseconds, elementId, count, timeout, onSuccessFunction);
}
else {
if (elementSearchStatus == ElementSearchStatus.Found) {
onSuccessFunction();
}
}
}
function existsElement(elementId, count, timeout) {
var foundElements = $("#" + elementId);
if (foundElements.length > 0 || count > timeout) {
if (foundElements.length > 0) {
console.log(elementId + " found");
return ElementSearchStatus.Found;
}
else {
console.log("Search for " + elementId + " timed out after " + count + " tries.");
return ElementSearchStatus.Timeout;
}
}
else {
console.log("waiting for " + elementId + " after " + count + " of " + timeout);
return ElementSearchStatus.None;
}
}
function main() {
waitForElement("StartButton", 0, maxTimeout, function () {
console.log("found StartButton!");
DoOtherStuff("StartButton2")
});
}
function DoOtherStuff(elementId) {
waitForElement(elementId, 0, maxTimeout, function () {
console.log("found " + elementId);
DoOtherStuff("StartButton3");
});
}
</script>
</head>
<body>
<button type="button" id="StartButton" onclick="main();">Start Test</button>
<button type="button" id="StartButton2" onclick="alert('Hey ya Start Button 2');">Show alert</button>
</body>
</html>
我有这个问题很久了,我需要的答案并不完全是这里提供的。此等待函数会导致同步等待,而不会占用CPU。
函数waitForIt向任何地方发出Ajax请求,并将异步标志设置为false。函数waitF对一个帧执行相同的操作,函数waitD对一个div执行相同的处理。Ajax大约需要100毫秒,frame大约是25,div大约是1。
wait函数根据您给它的时间来利用所有这些。如果它等待的时间不够长,请再次执行。
在处理多个异步加载元素时,我需要这个。基本上是“等待此元素存在”。你可以在https://jsfiddle.net/h2vm29ue/.它只是利用了浏览器自然等待的东西。较长的版本,https://jsfiddle.net/5cov1p0z/32/,更精确。
function waitForIt() {
var start = new Date();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Doesn't matter
}
};
xhttp.open("GET", "WaitForIt", false);
xhttp.send();
var end = new Date();
}
//
function waitF() {
var start = new Date();
var ifram = document.createElement('iframe');
ifram.id = 'ifram';
ifram.src = '';
var div = document.createElement('div');
div.id = 'timer';
document.body.appendChild(div);
document.getElementById('timer').appendChild(ifram);
document.getElementById('timer').removeChild(ifram);
document.body.removeChild(div);
var end = new Date();
return (end - start);
}
function waitD() {
var start = new Date();
var div = document.createElement('div');
div.id = 'timer';
document.body.appendChild(div);
div.click();
document.body.removeChild(div);
var end = new Date();
return (end - start);
}
function wait(time) {
var start = new Date();
var end = new Date();
while ((end - start < time)) {
if ((time - (end - start)) >= 200) {
waitForIt();
} else {
if ((time - (end - start)) >= 50) {
waitF();
} else {
waitD();
}
}
end = new Date();
}
return (end - start);
}
一种非常简单的睡眠方式,它将与运行JavaScript的任何东西兼容。。。这段代码已经过500个条目的测试,CPU和内存的使用情况在我的web浏览器上仍然不可见。
这里有一个函数,它等待节点变为可见。。。
此函数创建一个新的上下文函数(){}以避免递归。我们在这个新上下文中放置了与调用者代码相同的代码。我们使用函数Timeout在几秒钟后调用我们的函数。
var get_hyper = function(node, maxcount, only_relation) {
if (node.offsetParent === null) {
// node is hidden
setTimeout(function () { get_hyper(node, maxcount, only_relation)},
1000);
return;
};
// Enter the code here that waits for that node becoming visible
// before getting executed.
};
如果您真的需要等待那么多秒,那么当前接受的使用async/await和setTimeout的解决方案是完美的。然而,如果您将其用于屏幕动画,则应该真正使用requestAnimationFrame()。此函数的功能与setTimeout非常相似,但回调仅在用户可见动画时调用。这意味着,如果您在网站上运行动画,并且用户切换选项卡,动画将暂停并节省电池寿命。
这里是使用requestAnimationFrame的wait方法的实现。它接收多个帧,并在它们全部通过后解析:
常量动画等待=(帧)=>新承诺((决心)=>{让framesPassed=0;requestAnimationFrame(函数循环(){如果(++framesPassed>=帧)返回resolve();requestAnimationFrame(循环);});});//演示用打字机效果const content=document.querySelector(“.content”);异步函数类型Writer(endText,等待){content.textContent=“”;for(const letter of endText){content.textContent+=字母;wait animationWait(等待);}}typeWriter(“好的。这个简单的打字机效果是requestAnimationFrame的一个例子。”,8);<p>动画将在下面播放;尝试切换选项卡并查看动画暂停。</p><code class=“content”></code>
阅读有关requestAnimationFrame的更多信息
浏览器支持(IE10+)
使用三种功能:
调用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计算