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

cop*_*ake 262 javascript javascript-events

下面的这个功能不像我想要的那样工作; 作为一个JS新手我无法弄清楚为什么.

我需要它等待5秒才能检查是否newState-1.

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

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

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}
Run Code Online (Sandbox Code Playgroud)

Jos*_*ber 289

您必须将代码放在您提供的回调函数中setTimeout:

function stateChange(newState) {
    setTimeout(function () {
        if (newState == -1) {
            alert('VIDEO HAS STOPPED');
        }
    }, 5000);
}
Run Code Online (Sandbox Code Playgroud)

任何其他代码将立即执行.

  • 如果通过"测试"来表示单元测试:您的测试框架应该有一种方法来运行异步测试.如果您的意思是手动测试:Chrome的"网络"标签具有"限制"下拉菜单以模拟慢速请求. (12认同)
  • 主要问题是在某些情况下(特别是测试),这是非常不合适的.如果你需要在从函数返回之前休眠500ms,例如模拟一个_slow_ async http请求怎么办? (4认同)

Mic*_*Mic 158

你真的不应该这样做,正确使用超时是OP问题的正确工具,以及任何其他你想在一段时间后运行的东西.约瑟夫西尔伯在他的回答中证明了这一点.但是,如果在某些非生产情况下你真的想挂主线程一段时间,那就可以了.

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}
Run Code Online (Sandbox Code Playgroud)

在表单中执行:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');
Run Code Online (Sandbox Code Playgroud)

我来到这里是因为我正在构建一个简单的测试用例,用于对长时间运行的阻塞操作(即昂贵的DOM操作)的异步操作进行排序,这是我的模拟阻塞操作.它适合那种工作,所以我认为我发布给其他任何带有类似用例到达这里的人.即便如此,它还是在while循环中创建一个Date()对象,如果它运行得足够长,它可能会非常淹没GC.但我不能强调,这只适用于测试,建立任何实际功能,你应该参考约瑟夫西尔伯的答案.

  • @TerryLin尝试运行它. (19认同)
  • 这不会阻止javascript执行. (7认同)
  • 所以基本上你是在浪费CPU时间.这不是等待,因为您没有将线程置于睡眠模式,允许主处理器专注于其他任务. (6认同)
  • @Gzork Thread sleep只是实现等待函数的一种方法,遗憾的是它在客户端javascript的上下文中不可用.但是,如果您认为客户端中的其他异步任务将在运行时完成,那么您显然没有对其进行测试.虽然我会在主线程中使用它,但我总结了一个小提琴,说明如果首先通过setTimeout调用它,它仍然会中断其他异步事件https://jsfiddle.net/souv51v3/1/ - 你即使JSFiddle窗口本身在完成时也会变得无响应. (5认同)
  • 恕我直言,糟糕的解决方案——在“睡眠”时占用 CPU。正确的睡眠方式是通过 async/await 这个答案 /sf/ask/66571501/ 或 Etienne 的。 (2认同)
  • @DavidSimic 不幸的是,在编写此答案时,任何常见的浏览器 JavaScript 运行时都没有实现承诺。基于承诺的解决方案也不会阻塞主 UI 线程,这使得它们完全不适合我的用例(当时),原因与 setTimeout 无法实现相同。如果您对 CPU 使用情况进行了基准测试,我会对结果感兴趣。 (2认同)

Eti*_*tin 112

这是使用新的async/await语法的解决方案.

请务必检查浏览器支持,因为这是ECMAScript 6引入的新功能.

辅助功能:

const delay = ms => new Promise(res => setTimeout(res, ms));
Run Code Online (Sandbox Code Playgroud)

用法:

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

  await delay(5000);
  console.log("Waited an additional 5s");
};
Run Code Online (Sandbox Code Playgroud)

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

  • 这确实是新语法的最佳答案。我在使用上面的 wait() 解决方案时遇到了问题。 (4认同)
  • 简言之: ```const delay = async (ms: number) =&gt; new Promise(res =&gt; setTimeout(res, ms));``` (2认同)
  • 用于记录和将来的搜索:这对于实际使用 Selenium 与 Javascript 和 React 的人来说非常有帮助,因为您可以等待几秒钟,而 React 在例如下拉选择之后重新计算页面。 (2认同)

jfr*_*d00 34

你不应该只是尝试在javascript中暂停5秒.它不起作用.您可以安排代码函数从现在开始运行5秒,但是您必须将稍后要运行的代码放入函数中,并且该函数之后的其余代码将继续立即运行.

例如:

function stateChange(newState) {
    setTimeout(function(){
        if(newState == -1){alert('VIDEO HAS STOPPED');}
    }, 5000);
}
Run Code Online (Sandbox Code Playgroud)

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

stateChange(-1);
console.log("Hello");
Run Code Online (Sandbox Code Playgroud)

console.log()声明将立即运行.它不会等到stateChange()函数超时触发后才会触发.你不能只是暂停javascript执行一段预定的时间.

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

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

  • **你不能暂停javascript执行一段预定的时间**.我认为你的意思是你不应该,因为你*可以*(如果你想自己挂起):`var t = new Date().getTime(); while(new Date().getTime()<t + millisecondsToLockupBrowser);` (31认同)
  • 好吧*当然*那将是可怕的,没有人应该*永远都不会*那样做.我无法抗拒我的内心["实际上很好"](http://tirania.org/blog/archive/2011/Feb-17.html).抱歉. (12认同)
  • @JosephSilber - 好的,你可以做到这一点,但实际上这不起作用,因为许多浏览器会建立一个对话框,说脚本已经没有响应,这是一个糟糕的用户体验,它对电池寿命有害,页面是在这样做时挂起......那会很糟糕. (9认同)

Kai*_*ack 33

使用这样的延迟函数:

var delay = ( function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
})();
Run Code Online (Sandbox Code Playgroud)

用法:

delay(function(){
    // do stuff
}, 5000 ); // end delay
Run Code Online (Sandbox Code Playgroud)

积分转到用户CMS,请参阅如何延迟.keyup()处理程序,直到用户停止输入?


Shl*_*Shl 20

如果您处于异步功能中,则只需在一行中执行:

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

请注意,如果target是NodeJS,使用它会更有效(它是预定义的promisified setTimeout函数):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec
Run Code Online (Sandbox Code Playgroud)

  • 两种实现有什么区别? (2认同)
  • 目前,没有区别。但是,如果在某个时候 Node 决定让它更快/更安全/更高效,那么您将预先使用 Node js 版本。尽管可读性对于大多数人来说更有可能是关键因素,在这种情况下你最好使用第一种方法。 (2认同)

bea*_*a13 11

此解决方案来自React Native 的刷新控件文档

function wait(timeout) {
    return new Promise(resolve => {
        setTimeout(resolve, timeout);
    });
}
Run Code Online (Sandbox Code Playgroud)

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

await wait(5000);
if (newState == -1) {
    alert('Done');
}
Run Code Online (Sandbox Code Playgroud)


小智 10

如果你有一个异步函数,你可以这样做:

await new Promise(resolve => setTimeout(resolve, 5000));
Run Code Online (Sandbox Code Playgroud)


Jit*_* JP 7

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

function waitSeconds(iMilliSeconds) {
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) {
        end = new Date().getTime();
        counter = end - start;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是这个问题的唯一错误答案 - 你不应该让 JS 代码陷入循环,因为它是单线程的。此外,您让计算机无缘无故地循环工作,而不是使用事件。 (2认同)

Ste*_*ang 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不管用.主代码将继续执行 (5认同)

p.d*_*kar 6

您可以通过对函数( 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();
Run Code Online (Sandbox Code Playgroud)


小智 6

setTimeout(function() {
     $('.message').hide();
}, 5000);
Run Code Online (Sandbox Code Playgroud)

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

  • 他想知道如何在执行其他行之前等待 5 秒,而不是如何在 2 秒后执行代码 (2认同)

Syl*_*are 5

根据 Joseph Silber 的回答,我会这样做,更通用一点。

你会有你的功能(让我们根据问题创建一个):

function videoStopped(newState){
   if (newState == -1) {
       alert('VIDEO HAS STOPPED');
   }
}
Run Code Online (Sandbox Code Playgroud)

你可以有一个等待功能:

function wait(milliseconds, foo, arg){
    setTimeout(function () {
        foo(arg); // will be executed after the specified time
    }, milliseconds);
}
Run Code Online (Sandbox Code Playgroud)

最后你会有:

wait(5000, videoStopped, newState);
Run Code Online (Sandbox Code Playgroud)

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