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

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

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


当前回答

我也搜索了一个睡眠解决方案(不用于生产代码,只用于开发和测试),并找到了这篇文章:

JavaScript sleep()或wait()

…还有一篇关于客户端解决方案的文章:JavaScript睡眠

此外,当您调用alert()时,代码也会暂停,同时显示警报——您需要找到一种方法来不显示警报,但获得相同的效果。:)

其他回答

这里的大多数答案都是错误的,或者至少是过时的。没有理由JavaScript必须是单线程的,事实上也不是。今天,所有主流浏览器都支持工人。在此之前,Rhino和Node.js等其他JavaScript运行时支持多线程。

“JavaScript是单线程的”不是有效答案。例如,在工作线程中运行睡眠函数不会阻止UI线程中运行的任何代码。

在支持生成器和yield的较新运行时中,可以在单线程环境中为sleep函数带来类似的功能:

// This is based on the latest ES6 drafts.
// JavaScript 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// Run code you want to sleep here (omit star if using JavaScript 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // To sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// Resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // Omit .value if using JavaScript 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// Initialize a generator and get first sleep for the recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// Initialize recursive resume function
resume(firstSleep, generator);

这种对睡眠的模仿不同于真正的睡眠函数,因为它不会阻塞线程。它只是JavaScript当前setTimeout函数之上的糖。这种功能类型已经在Task.js中实现,现在应该可以在Firefox中使用。

我得到了Promise不是一个使用顶级答案的构造函数。如果你进口蓝鸟,你可以做到这一点。在我看来,这是最简单的解决方案。

import * as Promise from 'bluebird';

await Promise.delay(5000)

我会将setTimeOut封装在Promise中,以实现与其他异步任务的代码一致性:Fiddle中的Demo

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

它的用法如下:

sleep(2000).then(function() {
   // Do something
});

如果您习惯使用Promise,那么很容易记住语法。

如果你写一个这样的睡眠函数

var sleep = function(period, decision, callback){
    var interval = setInterval(function(){
        if (decision()) {
            interval = clearInterval(interval);
            callback();
        }
    }, period);
}

你有一个异步函数可以多次调用,

var xhr = function(url, callback){
    // Make an Ajax request
    // Call a callback when the request fulfils
}

您的项目设置如下:

var ready = false;

function xhr1(){
    xhr(url1, function(){ ready = true;});
}
function xhr2(){
    xhr(url2, function(){ ready = true; });
}
function xhr3(){
    xhr(url3, function(){ ready = true; });
}

然后您可以执行以下操作:

xhr1();
sleep(100, function(){ return done; }, xhr2);
sleep(100, function(){ return done; }, xhr3);
sleep(100, function(){ return done; }, function(){
    // Do more
});

而不是像这样无休止的回调缩进:

xhr(url1, function(){
    xhr2(url2, function(){
        xhr3(url3, function(){
            // Do more
        });
    });
});

使用三种功能:

调用setInterval启动循环的函数一个函数,它调用clearInterval来停止循环,然后调用setTimeout来休眠,最后在setTimeout内调用作为回调来重新启动循环一个循环,跟踪迭代次数,设置睡眠次数和最大次数,一旦达到睡眠次数就调用睡眠函数,并在达到最大次数后调用clearInterval

var foo={};函数main(){“使用严格”;/*初始化全局状态*/foo.bar=foo.bar ||0;/*初始化计时器*/foo.bop=设置间隔(foo.baz,1000);}睡眠=功能(计时器){“使用严格”;clearInterval(计时器);timer=setTimeout(function(){main()},5000);};foo.baz=函数(){“使用严格”;/*更新状态*/foo.bar=数字(foo.bar+1)||0;/*日志状态*/console.log(foo.bar);/*检查状态并在10时停止*/(foo.bar===5)&&睡眠(foo.bop);(foo.bar==10)&&clearInterval(foo.bop);};main();

工具书类

使用JavaScript开发游戏为什么iOS 8中的滚动事件更改是一件大事Ember.js中的实时轮询系统使用requestAnimationFrame()驱动动画MDN:JavaScript并发模型和事件循环网格研究:Node.js在JavaScript中超过60fps第2部分:不阻塞单个线程的CPU密集型JavaScript计算