延迟使用Javascript


73

我需要在Javascript代码中添加大约100毫秒的延迟,但是我不想使用对象的setTimeout功能,window也不想使用繁忙的循环。有没有人有什么建议?


18
您能解释一下为什么setTimeout不适合/不满足您的需求吗?
眼睑失明

@eyelidessness有时插入的setTimeout(...)它可能涉及不必更新的单元测试整个负载,使用开玩笑假定时器等等
AndyUK

Answers:


138

不幸的是,这setTimeout()是在不阻塞UI的情况下暂停脚本执行的唯一可靠方法(不是唯一方法,而是唯一可靠方法)。

实际上,使用它并不难,而不需要编写以下代码:

var x = 1;

// Place mysterious code that blocks the thread for 100 ms.

x = x * 3 + 2;
var y = x / 2;

您可以setTimeout()通过以下方式重写它:

var x = 1;
var y = null; // To keep under proper scope

setTimeout(function() {
    x = x * 3 + 2;
    y = x / 2;
}, 100);

我知道使用setTimeout()比需要的sleep()功能涉及更多的思考,但是不幸的是,后者并不存在。有许多解决方法可以尝试实现这些功能。一些使用忙循环:

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

其他的使用XMLHttpRequest与服务器脚本捆绑在一起的脚本,在返回结果之前会休眠一段时间

不幸的是,这些是变通办法,并且可能导致其他问题(例如冻结浏览器)。建议您坚持使用推荐的方法,即setTimeout())。


3
@James M .:完全同意...我从来不明白为什么周围会有如此大的污名setTimeout()
Andrew Moore

3
我不相信setTimeout()周围有任何污名,只是它并不总是容易产生所需的效果。举例来说,假设您想在处理器密集型循环中使处理器空闲一小段时间,以避免锁定浏览器。对于没有经验的JavaScript程序员,使用setTimeout实现此结果可能很困难。
KingRadical

1
该脚本对我的工作时间约为9秒。之后,它会停留约9秒钟。也许就是那个1e7价值?
内森H

“但是不幸的是,后者不存在。” 您是说“后”吗?
FluorescentGreen5

我是JS新手。我怎么称呼上面的延迟脚本?我有一个循环即时通讯试图延迟使用此功能。我尝试了功能睡眠(2000){...}。但这不起作用。
user982853 '19

15

如果您对ES2017没问题,那就await很好:

const DEF_DELAY = 1000;

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms || DEF_DELAY));
}

await sleep(100);

请注意,该await部分需要处于异步函数中:

//IIAFE (immediately invoked async function expression)
(async()=>{
  //Do some stuff
  await sleep(100);
  //Do some more stuff
})()

14

我有一个问题需要适当解决。

通过Ajax,脚本获得X(0-10)条消息。我想做的是:每10秒向DOM添加一条消息。

我最终得到的代码是:

$.each(messages, function(idx, el){
  window.setTimeout(function(){
    doSomething(el);
  },Math.floor(idx+1)*10000);
});

基本上,将超时视为脚本的“时间轴”。

这就是我们想要编写的代码:

DoSomething();
WaitAndDoNothing(5000);
DoSomethingOther();
WaitAndDoNothing(5000);
DoEvenMore();

这就是我们需要如何向Javascript讲述的方法:

At Runtime 0    : DoSomething();
At Runtime 5000 : DoSomethingOther();
At Runtime 10000: DoEvenMore();

希望这可以帮助。


感谢您回答SetTimeOut行为的答案。问题是,稍后代码较长或取决于服务器响应时,甚至很难在几秒钟内可视化实际时间轴。
Gaurav Ojha

3

实际上,setTimeout对于该工作而言仅是很好的选择,通常,您无法使用不确定的方法将精确的延迟设置为忙循环。


您无法使用setTimeout暂停js解释器。
阿伦·阿拉维德

您只能在延迟后调用函数。setTimeout不是“阻止”。其余代码按预期工作。
阿伦·阿拉维德

2

该线程进行了很好的讨论和有用的解决方案:

function pause( iMilliseconds )
{
    var sDialogScript = 'window.setTimeout( function () { window.close(); }, ' + iMilliseconds + ');';
    window.showModalDialog('javascript:document.writeln ("<script>' + sDialogScript + '<' + '/script>")');
}

不幸的是,这似乎在某些版本的IE中不起作用,但是如果证明这对您来说是一个问题,则该线程还有许多其他有价值的建议。


2
似乎是等待问题的解决方案。我想不出一个setTimeout无法胜任的情况。但是+1为创造力。:)
Sasha Chedygov

-11

使用AJAX函数,该函数将同步调用php页面,然后在该页面中放置php usleep()函数,该函数将起到延迟作用。

function delay(t){

var xmlhttp;

if (window.XMLHttpRequest)

{// code for IE7+, Firefox, Chrome, Opera, Safari

xmlhttp=new XMLHttpRequest();

}

else

{// code for IE6, IE5

xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

}

xmlhttp.open("POST","http://www.hklabs.org/files/delay.php?time="+t,false);

//This will call the page named delay.php and the response will be sent to a division with ID as "response"

xmlhttp.send();

document.getElementById("response").innerHTML=xmlhttp.responseText;

}

http://www.hklabs.org/articles/put-delay-in-javascript


16
不要忘记网页设计的基础知识。基本原则是尽可能减少服务器负载。对于一个简单的时间延迟,您需要无限次从服务器请求一个页面。只是想想你在这里做什么。
阿伦·阿拉维德

您已经杀了他
亚历克斯·霍金
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.