在特定延迟后使用JavaScript执行脚本


189

是否有任何类似于jQuery的JavaScript方法delay()wait()(将脚本的执行延迟特定时间)?

Answers:


189

有以下内容:

setTimeout(function, milliseconds);

该函数可以在执行该函数之前经过的时间传递。

请参阅:窗口setTimeout()方法


3
它不是一个执行的表达式,而是一个函数。@Marius的回答说明了这一点。
pedrofurla 2012年

117
这不是拖延,而是分叉。延迟应该在同一线程中工作。
DragonLord 2012年

13
这将立即执行function_reference。要“异步”工作,应声明为:setTimeout(function(){MethodToCall();},1000);
Bernoulli IT

6
我想指出的是,我们在谈论JavaScript。提出“线程”或使其“同步”工作在技术上语义上可能是正确的,但实际上并不适合JavaScript的上下文,考虑到使用这两种方法实际上都无法实现延迟(您不会就像在其他语言中一样在JS中创建“线程”)。另外,function_reference除非包含在内,否则不会立即执行()。即function_reference仅仅是-参考;传入function_reference()将立即调用该函数。
丹尼·布利斯

237

只是添加到其他人都说过的内容上setTimeout:如果将来要使用参数调用函数,则需要设置一些匿名函数调用。

您需要将函数作为参数传递,以便稍后调用。实际上,这意味着名称后没有方括号。以下将立即调用警报,并显示“ Hello world”:

var a = "world";
setTimeout(alert("Hello " + a), 2000);

要解决此问题,您可以输入函数名称(如Flubba所做的那样),也可以使用匿名函数。如果需要传递参数,则必须使用匿名函数。

var a = "world";
setTimeout(function(){alert("Hello " + a)}, 2000);
a = "Stack Overflow";

但是,如果运行该代码,您会注意到2秒钟后,弹出窗口将显示“ Hello Stack Overflow”。这是因为变量a的值在那两秒钟内发生了变化。要在两秒钟后说出“ Hello world”,您需要使用以下代码片段:

function callback(a){
    return function(){
        alert("Hello " + a);
    }
}
var a = "world";
setTimeout(callback(a), 2000);
a = "Stack Overflow";

它将等待2秒钟,然后弹出“ Hello world”。


37

只是扩大一点...您可以直接在setTimeout调用中执行代码,但是正如@patrick所说,通常会分配一个回调函数,如下所示。时间以毫秒为单位

setTimeout(func, 4000);
function func() {
    alert('Do stuff here');
}

27

如果您真的想拥有阻塞(同步)delay功能(无论如何),为什么不这样做:

<script type="text/javascript">
    function delay(ms) {
        var cur_d = new Date();
        var cur_ticks = cur_d.getTime();
        var ms_passed = 0;
        while(ms_passed < ms) {
            var d = new Date();  // Possible memory leak?
            var ticks = d.getTime();
            ms_passed = ticks - cur_ticks;
            // d = null;  // Prevent memory leak?
        }
    }

    alert("2 sec delay")
    delay(2000);
    alert("done ... 500 ms delay")
    delay(500);
    alert("done");
</script>

2
该解决方案的困难在于它积极地使用处理器,这导致功耗增加,其他线程/进程(例如,其他选项卡,其他程序)的可用资源减少。相比之下,睡眠会暂时中止线程对系统资源的使用。
ramcdougal 2014年

1
最好使用Date.now()而不是新的Date(),并且不要考虑内存泄漏
WayFarer 2014年

1
当然,这是CPU密集型的,但是它可以用于快速而肮脏的测试
Maris B.15

我想要一个不会锁定线程的版本,因此我可以在delaying 之前刷新DOM (以回答此问题)。有什么办法吗?
Gui Imamura

3
一个更紧凑的例程:function delay(ms){var start_time = Date.now(); while(Date.now()-start_time <ms); }
公爵

15

您需要使用setTimeout并将其传递给回调函数。您无法在javascript中使用sleep的原因是因为您同时会阻止整个页面执行任何操作。这不是一个好计划。使用Javascript的事件模型并保持快乐。不要打!


2
仍然对测试有用。就像在提交新的HTTP请求之前将表单提交延迟几秒钟以评估页面更改一样。
2013年

1
@rushinge然后设置回调以提交表单并禁用默认表单提交
Populus

1
留下链接作为代码的好主意...现在不起作用。
Emmet Arries

1
或者您知道,我可以解决它。
帕特里克

14

您还可以使用window.setInterval()定期重复运行某些代码。


2
setInterval()不应使用setTimeout-
保罗,

9
setTimeout()做一次,setInterval()重复做一次。如果您希望代码每5秒运行一次,setInterval()就可以完成这项工作。
rcoup

11

为了补充前面的评论,我想说以下内容:

setTimeout()JavaScript中的函数本身不会暂停脚本的执行,而只是告诉编译器将来某个时候执行代码。

实际上,没有内置JavaScript函数可以暂停执行。但是,您可以编写自己的函数,执行无条件循环之类的操作,直到使用时间为止,方法是使用该Date()函数并添加所需的时间间隔。


11

如果只需要测试延迟,则可以使用以下方法:

function delay(ms) {
   ms += new Date().getTime();
   while (new Date() < ms){}
}

然后,如果要延迟2秒钟,请执行以下操作:

delay(2000);

虽然可能不是最适合生产的。评论中的更多内容


@ U2744雪花您能否尝试并在评论中更加精确
Christoffer

1
好吧,这是一个繁忙的循环,将耗尽笔记本电脑和其他移动设备的电量,并可能还会阻止UI响应(甚至显示)。
Ry-

@ U2744SNOWFLAKE很有道理。更新了答案,我使用此功能的原因是:)
Christoffer 2014年

2
在开发中可以很好地工作,以获得快速而又肮脏的(临时的)解决方案。
HumanInDisguise

5

您为什么不能将代码放在承诺的后面?(从我的头顶输入)

new Promise(function(resolve, reject) {
  setTimeout(resolve, 2000);
}).then(function() {
  console.log('do whatever you wanted to hold off on');
});


5

简单的答复是:

setTimeout(
    function () {
        x = 1;
    }, 1000);

上面的函数等待1秒钟(1000毫秒),然后将x设置为1。您可以在匿名函数内做任何您想做的事情。


4

我非常喜欢毛里乌斯用三种不同的致电方式做出的解释(最高的回应)setTimeout

在我的代码中,我想在完成AJAX保存事件后自动自动导航到上一页。保存事件的完成在CSS中略有动画,指示保存成功。

在我的代码中,我发现前两个示例有所不同:

setTimeout(window.history.back(), 3000);

这个函数不等待超时-不管我为延迟输入多少,back()都会立即被调用。

但是,将其更改为:

setTimeout(function() {window.history.back()}, 3000);

这正是我所希望的。

这并非特定于back()操作,与相同alert()。基本上alert()在第一种情况下使用时,将忽略延迟时间。当我关闭弹出窗口时,CSS的动画将继续。

因此,即使您使用的是内置函数而不使用参数,我也建议使用他描述的第二种或第三种方法。


1

我有一些ajax命令,希望在它们之间稍有延迟地运行。这是一种实现方法的简单示例。不过,由于我的非常规方法,我准备被撕成碎片。:)

//  Show current seconds and milliseconds
//  (I know there are other ways, I was aiming for minimal code
//  and fixed width.)
function secs()
{
    var s = Date.now() + ""; s = s.substr(s.length - 5);
  return s.substr(0, 2) + "." + s.substr(2);
}

//  Log we're loading
console.log("Loading: " + secs());

//  Create a list of commands to execute
var cmds = 
[
    function() { console.log("A: " + secs()); },
    function() { console.log("B: " + secs()); },
    function() { console.log("C: " + secs()); },
    function() { console.log("D: " + secs()); },
    function() { console.log("E: " + secs()); },
  function() { console.log("done: " + secs()); }
];

//  Run each command with a second delay in between
var ms = 1000;
cmds.forEach(function(cmd, i)
{
    setTimeout(cmd, ms * i);
});

// Log we've loaded (probably logged before first command)
console.log("Loaded: " + secs());

您可以复制代码块并将其粘贴到控制台窗口中,然后看到类似以下内容的内容:

Loading: 03.077
Loaded: 03.078
A: 03.079
B: 04.075
C: 05.075
D: 06.075
E: 07.076
done: 08.076

1

延迟调用函数的最简单解决方案是:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}

0

延迟功能:

/**
 * delay or pause for some time
 * @param {number} t - time (ms)
 * @return {Promise<*>}
 */
const delay = async t => new Promise(resolve => setTimeout(resolve, t));

内部用法async

await delay(1000);

-1

就像其他人说的那样,setTimeout是您最安全的选择,
但是有时您无法将逻辑分离到新函数中,那么可以使用Date.now()来获取毫秒数并自行进行延迟...。

function delay(milisecondDelay) {
   milisecondDelay += Date.now();
   while(Date.now() < milisecondDelay){}
}

alert('Ill be back in 5 sec after you click OK....');
delay(5000);
alert('# Im back # date:' +new Date());

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.