有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。


当前回答

内联函数:

(async () => await new Promise(resolve => setTimeout(resolve, 500)))();

500是VM在移动到下一行代码之前等待的时间(以毫秒为单位)。

tldr位;

基本上,当您创建一个promise时,它会在创建时返回一个可观察到的值,在回调中提供一个解析引用,用于在数据/响应可用时移交数据/响应。在这里,在500ms后通过setTimeOut调用resolve,直到未执行resolve之前,外部作用域正在等待进一步的处理,因此,创建了一个伪块。这与非阻塞(或调用其他语言中可用的非线程保留睡眠)完全不同,因为线程和最可能的UI以及网页/节点应用程序的任何其他正在进行的任务将被阻塞,而主线程将专门用于等待承诺解决。

其他回答

在服务器端,您可以使用deasync sleep()方法,该方法在C中本地实现,因此它可以有效地实现等待效果,而不会阻塞事件循环或将CPU置于100%负载。

例子:

#!/usr/bin/env node

// Requires `npm install --save deasync`
var sleep = require("deasync").sleep;

sleep(5000);

console.log ("Hello World!!");

但是,如果您需要一个纯JavaScript函数(例如,通过浏览器在客户端运行它),我很抱歉地说,我认为您的pausecomp()函数是实现它的唯一方法,而且,除此之外:

这不仅会暂停函数,还会暂停整个事件循环。因此,将不会参加其他活动。它使您的CPU处于100%负载。

因此,如果您需要它作为浏览器脚本,并且不希望出现这些可怕的效果,我必须说,您应该以某种方式重新思考您的功能:

a) 。您可以在超时时调用它(或调用do_the_rest()函数)。如果您不期望从函数中得到任何结果,则使用更简单的方法。

b) 。或者,如果你需要等待结果,那么你应该使用promise(当然,也可以使用回调地狱;-))。

无预期结果示例:

function myFunc() {

    console.log ("Do some things");

    setTimeout(function doTheRest(){
        console.log ("Do more things...");
    }, 5000);

    // Returns undefined.
};

myFunc();

返回promise的示例(注意它会改变函数的用法):

function myFunc(someString) {

    return new Promise(function(resolve, reject) {

        var result = [someString];
        result.push("Do some things");

        setTimeout(function(){
            result.push("Do more things...");
            resolve(result.join("\n"));
        }, 5000);
    });
};


// But notice that this approach affect to the function usage...
// (It returns a promise, not actual data):
myFunc("Hello!!").then(function(data){
    console.log(data);
}).catch(function(err){
    console.error(err);
});

这里大多数解决方案的问题是它们倒带堆栈。在某些情况下,这可能是一个大问题。在这个例子中,我展示了如何以不同的方式使用迭代器来模拟真实的睡眠。

在本例中,生成器正在调用自己的next(),因此一旦它启动,它就自己运行了。

var h = a();
h.next().value.r = h; // That's how you run it. It is the best I came up with

// Sleep without breaking the stack!!!
function *a(){
    var obj = {};

    console.log("going to sleep....2s")

    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("woke up");
    console.log("going to sleep no 2....2s")
    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("woke up");
    console.log("going to sleep no 3....2s")

    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("done");
}

2017-2021更新

自2009年提出这个问题以来,JavaScript已经有了很大的发展。所有其他答案现在都过时或过于复杂。以下是当前的最佳实践:

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

或作为一个内衬:

await new Promise(r => setTimeout(r, 2000));

作为一项功能:

const sleep = ms => new Promise(r => setTimeout(r, ms));

或使用字体:

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

将其用作:

await sleep(<duration>);

演示:

功能睡眠(ms){return new Promise(resol=>setTimeout(resolve,ms));}异步函数demo(){for(设i=0;i<5;i++){console.log(`等待${i}秒…`);等待睡眠(i*1000);}console.log('Done');}demo();

注意,

await只能在前缀为async关键字的函数中执行,或者在越来越多的环境中在脚本的顶层执行。await只暂停当前的异步函数。这意味着它不会阻止脚本的其余部分的执行,这在大多数情况下都是您想要的。如果您确实需要一个阻塞构造,请使用Atomics.wait查看这个答案,但请注意,大多数浏览器都不允许在浏览器的主线程上使用它。

两个新的JavaScript功能(截至2017年)帮助编写了这个“睡眠”函数:

Promises是ES2015(又称ES6)的原生功能。我们还在睡眠函数的定义中使用箭头函数。async/await特性允许代码显式地等待承诺(解决或拒绝)。

兼容性

承诺在Node v0.12+中得到支持,在浏览器中得到广泛支持,IE除外async/await登陆V8,自Chrome 55(2016年12月发布)以来默认启用它于2016年10月登陆Node 7并于2016年11月登陆Firefox Nightly

如果出于某种原因,您使用的Node早于7(已于2017年到期),或者针对的是旧浏览器,则仍可通过Babel(一种将JavaScript+新功能转换为普通旧JavaScript的工具)使用async/await,并使用将async-to-generator转换为生成器插件。

Use:

等待新的Promise(resol=>setTimeout(resolve,2000));

确保调用函数是异步的。这是经过验证的,工作正常。

这会帮你的。

var reloadAfter = 10; //seconds
var intervalId = setTimeout(function() {
    //code you want to execute after the time waiting
}, reloadAfter * 1000); // 60000 = 60 sec = 1 min