如何在JavaScript中进行REAL sleep()?

时间:2011-02-01 02:55:11

标签: javascript

我知道有很多方法,比如setTimeout,但我只想要一个真实的。

我正在使用JavaScript编写编译器,我必须找到一种方法来实现sleep()函数。 我知道那种错误的循环方式,这不是我想要的。

感谢。

5 个答案:

答案 0 :(得分:5)

从上面的答案我收集到你想要一个不会冻结浏览器并且不使用setTimeout的睡眠功能。

祝你好运,javascript是单线程的。 这是不可能的

答案 1 :(得分:4)

至少在大多数浏览器实现中,你不能。你必须让你的编译器解决这个问题。 StratifiedJS做了类似的事情。

我将添加更多细节。显然,这不是实现睡眠功能的最佳方式,但是既然你说你正在做一个简单的绘图语言,我就会这样做:

想象一下你有这样的代码:

drawLine(1, 2, 3, 4);
sleep(1000);
drawLine(5, 6, 7, 8);

可以通过分解所有sleep s:

将其转换为此
var pieces;
function advance() {
    pieces.shift()();
}
pieces=[
    function() {
        drawLine(1, 2, 3, 4);
        setTimeout(advance, 1000);
    },
    function() {
        drawLine(5, 6, 7, 8);
    }
];
advance();

或者,如果您的语言比这更复杂,那么编译器可能会更复杂(这是显而易见的解决方案):

drawLine(1, 2, 3, 4);
setTimeout(function() {
    drawLine(5, 6, 7, 8);
}, 1000);

同样,如果您的语言非常复杂,这可能不适用,但它可能有助于作为起点。

答案 2 :(得分:2)

听起来像你想要一个阻止循环

while(condition) {
    // do something
    sleep(x);
}

并将其转换为

function foo(values) {
    if(condition) {
         // do something
         setTimeout(function() {
            foo(values); 
         }, x);
    }
}
foo(someValue);

你也可以进行for循环

for (var i = 0; i < n; i++) {
    // do something
    sleep(x);
}

并将其转换为

function foo(i) {
    // do something
    i++;
    if (i < n) {
        setTimeout(function() {
            foo(i);
        }, x);
    }
}
foo(0);

基本上将你的循环转换为递归调用,然后用异步递归调用替换你的睡眠。

在循环中,您需要物理阻止以减慢步骤。在递归中,您可以将调用延迟到下一个递归函数。

答案 3 :(得分:1)

在JavaScript中实现sleep()的唯一真实且合理的方式(至少在浏览器环境中)是使用setTimeout。只需逐个处理编译的指令,然后在遇到睡眠指令时休息一下:

function resume() {
    while (instructions.length) {
        var instruction = instructions.shift();

        switch (instruction.opcode) {
        case "foo":
            doFoo(instruction.operands);
            break;
        case "bar":
            doBar(instruction.operands);
            break;
        case "sleep":
            doSleep(instruction.operands);
            return; // pause running
        }
    }
}

function doSleep(operands) {
    setTimeout(resume, operands[0]);
}

var instructions = compile(source);
resume();

答案 4 :(得分:0)

如果您只想在X毫秒内调用一个函数,可以使用setTimeout,但是您知道。

您可以使用日期和getTime一起破解。

function sleep(milliseconds) {
    var now = new Date();
    var exitTime = now.getTime() + milliseconds;
    while (true) {
        now = new Date();
        if (now.getTime() > exitTime)
        return;
    }
}

<强> stolen from here

然而您可能会在很长一段时间内完全冻结当前线程。我认为你基本上会停止页面上的所有javscript动作X毫秒,如果时间大于300毫秒,这将是非常烦人。

<强> there's some pretty good analysis of javscript sleep methods here.

如果你给我们一点上下文,我们可能会更有帮助。睡眠通常用于其他语言的多线程场景,这正是为什么没有javascript。您的编译器需要哪些功能? :d