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

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

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


当前回答

使用三种功能:

调用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计算

其他回答

这可以使用Java的睡眠方法来完成。我已经在Firefox和Internet Explorer中测试过它,它不会锁定计算机,不会占用资源,也不会导致无休止的服务器攻击。对我来说,这似乎是一个干净的解决方案。

首先,您必须在页面上加载Java并使其方法可用。为了做到这一点,我这样做了:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

然后,当您想要在JavaScript代码中轻松暂停时,您需要做的就是:

java.lang.Thread.sleep(xxx)

其中xxx是以毫秒为单位的时间。在我的案例中(作为理由),这是一家非常小的公司后端订单履行的一部分,我需要打印一张必须从服务器加载的发票。我是通过将发票(作为网页)加载到iFrame中,然后打印iFrame来完成的。

当然,我必须等到页面完全加载后才能打印,所以JavaScript代码必须暂停。我通过让发票页面(在iFrame中)使用onLoad事件更改父页面上的隐藏表单字段来实现这一点。打印发票的父页面上的代码如下(为清晰起见,将不相关的部分切割):

var isReady = eval('document.batchForm.ready');
isReady.value = 0;

frames['rpc_frame'].location.href = url;

while (isReady.value == 0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

因此,用户按下按钮,脚本加载发票页面,等待,每季度检查一次发票页面是否完成加载,并弹出打印对话框,供用户将其发送到打印机。QED。

我有这个问题很久了,我需要的答案并不完全是这里提供的。此等待函数会导致同步等待,而不会占用CPU。

函数waitForIt向任何地方发出Ajax请求,并将异步标志设置为false。函数waitF对一个帧执行相同的操作,函数waitD对一个div执行相同的处理。Ajax大约需要100毫秒,frame大约是25,div大约是1。

wait函数根据您给它的时间来利用所有这些。如果它等待的时间不够长,请再次执行。

在处理多个异步加载元素时,我需要这个。基本上是“等待此元素存在”。你可以在https://jsfiddle.net/h2vm29ue/.它只是利用了浏览器自然等待的东西。较长的版本,https://jsfiddle.net/5cov1p0z/32/,更精确。

 function waitForIt() {
     var start = new Date();
     var xhttp = new XMLHttpRequest();
     xhttp.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
            // Doesn't matter
         }
     };
     xhttp.open("GET", "WaitForIt", false);
     xhttp.send();
     var end = new Date();
 }
 //

 function waitF() {
     var start = new Date();
     var ifram = document.createElement('iframe');
     ifram.id = 'ifram';
     ifram.src = '';
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     document.getElementById('timer').appendChild(ifram);
     document.getElementById('timer').removeChild(ifram);
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }


 function waitD() {
     var start = new Date();
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     div.click();
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }

 function wait(time) {
     var start = new Date();
     var end = new Date();
     while ((end - start < time)) {

         if ((time - (end - start)) >= 200) {
             waitForIt();
         } else {
             if ((time - (end - start)) >= 50) {
                 waitF();
             } else {
                 waitD();
             }
         }
         end = new Date();
     }
     return (end - start);
 }

对于希望将循环执行的一组调用隔开的特定情况,可以使用类似于下面代码的原型。如果没有原型,可以用setTimeout替换延迟函数。

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

在Firebug(可能还有其他JavaScript控制台)中,只有在指定的睡眠时间(…)之后,点击enter后才会发生任何事情

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}

使用示例:

函数sleepFor(sleepDuration){var now=new Date().getTime();而(newDate().getTime()<now+sleepDuration){/*什么都不做*/}}函数sleepThenAt(){sleepFor(2000);console.log(“您好,JavaScript睡眠!”);}sleepThenAt()

注:仅用于调试和开发

我相信有一百万种方法可以做得更好,但我想我可以通过创建一个对象来尝试一下:

// execute code consecutively with delays (blocking/non-blocking internally)
function timed_functions()
{
    this.myfuncs = [];
    this.myfuncs_delays = []; // mirrors keys of myfuncs -- values stored are custom delays, or -1 for use default
    this.myfuncs_count = 0; // increment by 1 whenever we add a function
    this.myfuncs_prev    = -1; // previous index in array
    this.myfuncs_cur    = 0; // current index in array
    this.myfuncs_next  = 0; // next index in array
    this.delay_cur     = 0; // current delay in ms
    this.delay_default = 0; // default delay in ms
    this.loop = false;      // will this object continue to execute when at end of myfuncs array?
    this.finished = false;  // are we there yet?
    this.blocking = true;   // wait till code completes before firing timer?
    this.destroy = false;   // <advanced> destroy self when finished


    this.next_cycle = function() {
        var that  = this;
        var mytimer = this.delay_default;

        if(this.myfuncs_cur > -1)
            if(this.myfuncs_delays[this.myfuncs_cur] > -1)
                mytimer = this.myfuncs_delays[this.myfuncs_cur];

        console.log("fnc:" + this.myfuncs_cur);
        console.log("timer:" + mytimer);
        console.log("custom delay:" + this.myfuncs_delays[this.myfuncs_cur]);
        setTimeout(function() {
        // Time is up! Next cycle...
        that.cycle();

    }, mytimer);
}

this.cycle = function() {

    // Now check how far we are along our queue.. is this the last function?
    if(this.myfuncs_next + 1 > this.myfuncs_count)
    {
        if(this.loop)
        {
            console.log('looping..');
            this.myfuncs_next = 0;
        }
        else
            this.finished = true;
    }

    // First check if object isn't finished
    if(this.finished)
        return false;

    // HANDLE NON BLOCKING //
    if(this.blocking != true) // Blocking disabled
    {
        console.log("NOT BLOCKING");
        this.next_cycle();
    }

    // Set prev = current, and current to next, and next to new next
    this.myfuncs_prev = this.myfuncs_cur;
    this.myfuncs_cur  = this.myfuncs_next;
    this.myfuncs_next++;

    // Execute current slot
    this.myfuncs[this.myfuncs_cur]();

    // HANDLE BLOCKING
    if(this.blocking == true)  // Blocking enabled
    {
        console.log("BLOCKING");
        this.next_cycle();
    }

    return true;
};

// Adders
this.add = {
    that:this,

    fnc: function(aFunction) {
        // Add to the function array
        var cur_key = this.that.myfuncs_count++;
        this.that.myfuncs[cur_key] = aFunction;
        // Add to the delay reference array
        this.that.myfuncs_delays[cur_key] = -1;
    }
}; // end::this.add

// setters
this.set = {
    that:this,

    delay: function(ms) {
        var cur_key = this.that.myfuncs_count - 1;
        // This will handle the custom delay array this.that.myfunc_delays
        // Add a custom delay to your function container

        console.log("setting custom delay. key: "+ cur_key + " msecs: " + ms);
        if(cur_key > -1)
        {
            this.that.myfuncs_delays[cur_key] = ms;
        }
        // So now we create an entry on the delay variable
    },

    delay_cur:      function(ms) { this.that.delay_cur = ms; },
    delay_default:  function(ms) { this.that.delay_default = ms; },
    loop_on:        function()   { this.that.loop = true; },
    loop_off:       function()   { this.that.loop = false; },
    blocking_on:    function()   { this.that.blocking = true; },
    blocking_off:   function()   { this.that.blocking = false; },

    finished:            function(aBool) { this.that.finished = true; }
}; // end::this.set


// Setters
this.get = {
    that:this,

    delay_default: function() { return this.that.delay_default; },
    delay_cur:     function() { return this.that.delay_cur; }
    }; // end::this.get

} // end:::function timed_functions()

使用方式如下:

// // // BEGIN :: TEST // // //

// Initialize
var fncTimer = new timed_functions;

// Set some defaults
fncTimer.set.delay_default(1000);
fncTimer.set.blocking_on();
// fncTimer.set.loop_on();
// fncTimer.set.loop_off();


// BEGIN :: ADD FUNCTIONS (they will fire off in order)
fncTimer.add.fnc(function() {
    console.log('plan a (2 secs)');
});
fncTimer.set.delay(2000); // Set a custom delay for previously added function

fncTimer.add.fnc(function() {
    console.log('hello world (delay 3 seconds)');
});
fncTimer.set.delay(3000);

fncTimer.add.fnc(function() {
    console.log('wait 4 seconds...');
});
fncTimer.set.delay(4000);

fncTimer.add.fnc(function() {
    console.log('wait 2 seconds');
});
fncTimer.set.delay(2000);

fncTimer.add.fnc(function() {
    console.log('finished.');
});
// END :: ADD FUNCTIONS


// NOW RUN
fncTimer.cycle(); // Begin execution


// // // END :: TEST // // //