在执行下一行之前等待 5 秒

Posted

技术标签:

【中文标题】在执行下一行之前等待 5 秒【英文标题】:Wait 5 seconds before executing next line 【发布时间】:2012-12-23 00:05:03 【问题描述】:

下面的这个函数不像我想要的那样工作;作为一个 JS 新手,我不知道为什么。

在检查 newState 是否为 -1 之前,我需要它等待 5 秒。

目前,它不等待,它只是立即检查。

function stateChange(newState) 
  setTimeout('', 5000);

  if(newState == -1) 
    alert('VIDEO HAS STOPPED');
  

【问题讨论】:

Execute script after specific delay using javascript的可能重复 【参考方案1】:

你必须把你的代码放在你提供给setTimeout的回调函数中:

function stateChange(newState) 
    setTimeout(function () 
        if (newState == -1) 
            alert('VIDEO HAS STOPPED');
        
    , 5000);

任何其他代码都会立即执行。

【讨论】:

主要问题是在某些情况下(特别是测试),这严重不足。如果您需要在从函数返回之前休眠 500 毫秒,例如模拟一个 slow 异步 http 请求怎么办? 如果你所说的“测试”是指单元测试:你的测试框架应该有办法运行异步测试。如果您指的是手动测试:Chrome 的网络标签有一个限制下拉菜单来模拟慢速请求。 如果我开发了一个 chrome 扩展并且注入脚本中的最后一个评估值应该给我结果;我需要一些延迟吗? 另见以下问题:***.com/questions/758688/…【参考方案2】:

这是一个使用 new async/await 语法的解决方案。

请务必查看browser support,因为这是 ECMAScript 6 引入的语言功能。

实用功能:

const delay = ms => new Promise(res => setTimeout(res, ms));

用法:

const yourFunction = async () => 
  await delay(5000);
  console.log("Waited 5s");

  await delay(5000);
  console.log("Waited an additional 5s");
;

这种方法的优点是它使您的代码看起来和行为像同步代码。

【讨论】:

不需要 ECMAScript 6:如果您已经使用 Promise 进行异步加载,并且只想模仿需要很长时间的链的一部分,您可以将此 wait() 函数添加到链条。 这确实是新语法的最佳答案。我在使用上面的 wait() 解决方案时遇到了问题。 简洁:const delay = async (ms: number) => new Promise(res => setTimeout(res, ms)); 用于记录和将来的搜索:这对于实际使用 Selenium 与 Javascript 和 React 的人非常有帮助,因为您可以等待几秒钟,而 React 会在重新计算页面之后重新计算页面。下拉选择。 @DonDiego 正是我的用例【参考方案3】:

您真的不应该这样做,正确使用 timeout 是解决 OP 问题以及您只想在一段时间后运行某些东西的任何其他场合的正确工具。 Joseph Silber 在他的回答中很好地证明了这一点。但是,如果在某些非生产情况下,您真的想将主线程挂起一段时间,这会做到。

function wait(ms)
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) 
     end = new Date().getTime();
  

以形式执行:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');

我来到这里是因为我正在构建一个简单的测试用例,用于围绕长时间运行的阻塞操作(即昂贵的 DOM 操作)对混合异步操作进行排序,这是我模拟的阻塞操作。它很适合这份工作,所以我想我把它贴给其他有类似用例的人。即便如此,它还是在一个 while 循环中创建了一个 Date() 对象,如果它运行的时间足够长,它可能会使 GC 不堪重负。但我怎么强调都不为过,这仅适用于测试,对于构建任何实际功能,您应该参考 Joseph Silber 的回答。

【讨论】:

这不会停止 javascript 的执行。 @TerryLin 尝试运行它。 所以基本上你在浪费 CPU 时间。这不是等待,因为您没有将线程置于睡眠模式,从而允许主处理器专注于其他任务。 @Gzork 线程睡眠只是实现等待功能的一种方式,不幸的是它在客户端javascript的上下文中不可用。但是,如果您认为客户端中的其他异步任务将在它运行时完成,那么您显然还没有测试它。虽然我会在主线程中使用它,但我整理了一个小提琴,说明即使首先通过 setTimeout 调用它,它仍然会中断其他异步事件jsfiddle.net/souv51v3/1 - 你会发现甚至 JSFiddle 窗口本身也会变成完成时无响应。 @DavidSimic 不幸的是,在编写此答案时,任何常见的浏览器 JavaScript 运行时都没有实现承诺。基于承诺的解决方案也不会阻塞主 UI 线程,这使得它们完全不适合我的用例(当时),原因与 setTimeout 没有实现它的原因相同。如果你对 CPU 使用率进行了基准测试,我会对结果感兴趣。【参考方案4】:

如果您在 async function 中,您只需一行即可完成:

console.log(1);
await new Promise(resolve => setTimeout(resolve, 3000)); // 3 sec
console.log(2);

仅供参考,如果目标是 NodeJS,您可以根据需要使用它(这是一个预定义的承诺 setTimeout 函数):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec

【讨论】:

这两种实现有什么区别? 目前没有区别。但是,如果在某个时候 node 决定让它更快/更安全/更高效,您将预先使用 node js 版本。虽然可读性更可能是大多数人的关键因素,但在这种情况下,您最好使用第一种方式。 谢谢。您的回答解决了我已经面临三天的问题。谢谢。【参考方案5】:

使用这样的延迟函数:

var delay = ( function() 
    var timer = 0;
    return function(callback, ms) 
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    ;
)();

用法:

delay(function()
    // do stuff
, 5000 ); // end delay

致谢:How to delay the .keyup() handler until the user stops typing?

【讨论】:

【参考方案6】:

您不应该只是尝试在 javascript 中暂停 5 秒。它不是那样工作的。您可以安排一个代码函数在 5 秒后运行,但是您必须将稍后要运行的代码放入一个函数中,该函数之后的其余代码将立即继续运行。

例如:

function stateChange(newState) 
    setTimeout(function()
        if(newState == -1)alert('VIDEO HAS STOPPED');
    , 5000);

但是,如果你有这样的代码:

stateChange(-1);
console.log("Hello");

console.log() 语句将立即运行。它不会等到stateChange() 函数中的超时触发之后。您不能只暂停 JavaScript 执行一段预定的时间。

相反,您想要运行延迟的任何代码都必须在setTimeout() 回调函数内(或从该函数调用)。

如果您确实尝试通过循环“暂停”,那么您实际上会“挂起”Javascript 解释器一段时间。因为 Javascript 仅在单个线程中运行您的代码,所以当您循环时,其他任何东西都无法运行(无法调用其他事件处理程序)。因此,循环等待某个变量更改将永远不会起作用,因为没有其他代码可以运行来更改该变量。

【讨论】:

您不能只暂停 JavaScript 执行一段预定的时间。我认为你的意思是你不应该这样做,因为你可以(如果你想上吊的话):var t = new Date().getTime(); while (new Date().getTime() &lt; t + millisecondsToLockupBrowser); @JosephSilber - 好的,你可以这样做,但实际上这不起作用,因为许多浏览器会弹出一个对话框,说脚本已经变得无响应,这是一种可怕的用户体验,它是对电池寿命不利,并且在这样做时页面被挂起......那会很糟糕。 当然那将是可怕的,没有人应该永远永远这样做。我无法抗拒我内心的"well-actually"。对不起。【参考方案7】:

试试这个:

//the code will execute in 1 3 5 7 9 seconds later
function exec() 
    for(var i=0;i<5;i++) 
        setTimeout(function() 
            console.log(new Date());   //It's you code
        ,(i+i+1)*1000);
    

【讨论】:

如果您想在调用回调函数之前等待一个固定的时间间隔,请尝试 setInterval() 像 background color toggle code 这样您不需要像 setTimeout() 那样的 for 循环索引。跨度> 【参考方案8】:

此解决方案来自React Native's documentation for a refresh control:

function wait(timeout) 
    return new Promise(resolve => 
        setTimeout(resolve, timeout);
    );

要将其应用于 OP 的问题,您可以将此功能与 await 配合使用:

await wait(5000);
if (newState == -1) 
    alert('Done');

【讨论】:

【参考方案9】:

创建这样一个等待毫秒的函数的最佳方法,此函数将等待参数中提供的毫秒:

function waitSeconds(iMilliSeconds) 
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) 
        end = new Date().getTime();
        counter = end - start;
    

【讨论】:

这实际上是这个问题的唯一错误答案——你不应该让 JS 代码卡在一个循环中,因为它是单线程的。此外,您正在使计算机无缘无故地循环工作,而不是使用事件。【参考方案10】:
setTimeout(function() 
     $('.message').hide();
, 5000);

这将在 5 秒后隐藏“.message”div。

【讨论】:

他想知道如何在执行另一行之前等待 5 秒而不是如何在 2 秒后执行代码 @LegendaryEmoji 然后将 2000 更新为 5000【参考方案11】:

基于 Joseph Silber 的 answer,我会这样做,更通用一点。

您将拥有自己的功能(让我们根据问题创建一个):

function videoStopped(newState)
   if (newState == -1) 
       alert('VIDEO HAS STOPPED');
   

你可以有一个等待功能:

function wait(milliseconds, foo, arg)
    setTimeout(function () 
        foo(arg); // will be executed after the specified time
    , milliseconds);

最后你会得到:

wait(5000, videoStopped, newState);

这是一个解决方案,我宁愿不在等待函数中使用参数(只有foo(); 而不是foo(arg);),但这只是示例。

【讨论】:

这是我见过的最简单的解决方案。【参考方案12】:

您可以通过对函数(async 和 await)进行小的更改来增加延迟。

const addNSecondsDelay = (n) => 
  return new Promise(resolve => 
    setTimeout(() => 
      resolve();
    , n * 1000);
  );


const asyncFunctionCall = async () 

  console.log("stpe-1"); 
  await addNSecondsDelay(5);
  console.log("step-2 after 5 seconds delay"); 



asyncFunctionCall();

【讨论】:

这很优雅,但是有什么方法可以参数化解析中的工作吗?比如关闭一个jquerui对话框?【参考方案13】:

使用 angularjs:

$timeout(function()
if(yourvariable===-1)
doSomeThingAfter5Seconds();

,5000)

【讨论】:

【参考方案14】:

新建Js函数

function sleep(delay) 
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
      

当您想延迟执行时调用该函数。在 int 中使用毫秒作为延迟值。

####Some code
 sleep(1000);
####Next line

【讨论】:

那会消耗太多资源。【参考方案15】:

我用它从 Edge 或 IE 运行 PC 游戏。并且在 7 秒后两个 self 都会关闭。

Firefox 和 Google Chrome 不能用于以这种方式启动游戏。

    <html>
    <body>
    <a href="E:\game\game.exe" name="game" onmouseout="waitclose(7000);"> game
    <img src="game.jpg"   ></a>
    <script>
    function waitclose(ms)
     var start = new Date().getTime();var end=start;
     while(end < start + ms) end = new Date().getTime();
    window.open('', '_self', ''); window.close();
    
    </script>
    </body>
    </html>

【讨论】:

以上是关于在执行下一行之前等待 5 秒的主要内容,如果未能解决你的问题,请参考以下文章

在执行下一行代码之前等待超时完成

puppeteer:在继续下一行之前等待 N 秒

Gremlin - 在执行下一行脚本之前等待 schema.drop() 完成

我如何让java在执行下一行之前等待一秒钟,而不使用try/catch [重复]

C# |控制台应用程序 |如何在执行下一行之前让程序等待(以毫秒为单位的时间)?

VBA 等待刷新电源查询以执行下一行代码