等待 5 秒再执行下一行

IT技术 javascript dom-events
2021-01-14 00:42:27

下面的这个功能不像我想要的那样工作;作为一个 JS 新手,我不明白为什么。

我需要它等待 5 秒钟,然后再检查是否newState-1.

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

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

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}
6个回答

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

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

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

如果“测试”是指单元测试:您的测试框架应该有办法运行异步测试。如果您的意思是手动测试:Chrome 的网络选项卡有一个限制下拉菜单来模拟慢速请求。
2021-03-17 00:42:27
另请参阅以下问题:stackoverflow.com/questions/758688/...
2021-03-17 00:42:27
主要问题是在某些情况下(特别是测试)这是非常不充分的。如果在从函数返回之前需要休眠 500 毫秒,例如模拟慢速异步 http 请求,该怎么办?
2021-04-07 00:42:27
如果我开发了一个 chrome 扩展并且注入脚本中的最后一个评估值应该给我结果怎么办;我需要一些延迟?
2021-04-09 00:42:27

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

请务必检查浏览器支持,因为这是 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");
};

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

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

您真的不应该这样做,正确使用超时是解决 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 的回答。

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

如果你在一个异步函数中,你可以简单地在一行中完成:

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

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

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec
目前,没有区别。但是如果在某个时候节点决定让它更快/更安全/更高效,你将预先使用节点 js 版本。尽管对大多数人来说,可读性更有可能是关键因素,但在这种情况下,您最好使用第一种方式。
2021-03-13 00:42:27
这两种实现有什么区别?
2021-03-16 00:42:27
谢谢你。您的回答解决了我已经面临三天的问题。谢谢。
2021-04-05 00:42:27

使用这样的延迟函数:

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

用法:

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

积分:如何延迟 .keyup() 处理程序直到用户停止输入?