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

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

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


当前回答

我使用多线程HTML5 Worker,它将能够中止指向无响应URL的同步XMLHttpRequest。这不会阻止浏览器。

https://gist.github.com/el-gringo/6990785

其他回答

2022年更新

只需使用此代码段。

await new Promise(resolve => setTimeout(resolve, 2000));
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

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

// 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 // // //

从该链接获取的代码不会冻结计算机。但它只在Firefox中有效。

/**
 * Netscape compatible WaitForDelay function.
 * You can use it as an alternative to Thread.Sleep() in any major programming language
 * that support it while JavaScript it self doesn't have any built-in function to do such a thing.
 * parameters:
 * (Number) delay in millisecond
 */
function nsWaitForDelay(delay) {
    /**
     * Just uncomment this code if you're building an extension for Firefox.
     * Since Firefox 3, we'll have to ask for user permission to execute XPCOM objects.
     */
    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

    // Get the current thread.
    var thread = Components.classes["@mozilla.org/thread-manager;1"].getService(Components.interfaces.nsIThreadManager).currentThread;

    // Create an inner property to be used later as a notifier.
    this.delayed = true;

    /* Call JavaScript setTimeout function
      * to execute this.delayed = false
      * after it finishes.
      */
    setTimeout("this.delayed = false;", delay);

    /**
     * Keep looping until this.delayed = false
     */
    while (this.delayed) {
        /**
         * This code will not freeze your browser as it's documented in here:
         * https://developer.mozilla.org/en/Code_snippets/Threads#Waiting_for_a_background_task_to_complete
         */
        thread.processNextEvent(true);
    }
}

第一:

定义要执行的函数,如下所示:

function alertWorld(){
  alert("Hello, World!");
}

然后使用setTimeout方法安排其执行:

setTimeout(alertWorld, 1000)

注意两件事

第二个参数是以毫秒为单位的时间作为第一个参数,必须只传递函数的名称(引用),而不传递括号