2

I know there are many methods like setTimeout, but I just want a REAL one.

I'm using JavaScript to write a compiler, and I have to find out a way to implement the sleep() function. I know that buggy loop way, it's not what I want.

Thanks.

Xhacker Liu
  • 1,578
  • 1
  • 16
  • 25

5 Answers5

5

From the answers above i gather that you want a sleep function that doesnt freeze the browser and doesnt use setTimeout.

Good luck with that, javascript is single threaded. This is NOT possible

mkoryak
  • 57,086
  • 61
  • 201
  • 257
4

You can't, at least in most browser implementations. You'll have to make your compiler work around that. StratifiedJS does something similar.

I'll add some more detail. This, obviously, is not the best way to implement a sleep function, but since you said you're doing a simple drawing language, I'll just go with this:

Imagine you have some code like this:

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

That could be converted into this by breaking up all the sleeps:

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

Or, if your language is more complex than that, you could do this with more complexity for the compiler (this is the obvious solution):

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

Again, this may not be applicable if your language gets very complex, but it may be helpful as a starting point.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • So you mean I can't implement the sleep() function? – Xhacker Liu Feb 01 '11 at 03:10
  • 1
    @Xhacker Liu: That's what I'm saying. You can, however, make your compiler convert the synchronous code into asynchronous code, therefore avoiding the issue. – icktoofay Feb 01 '11 at 03:11
  • Why does everyone still think that every Javascript program runs in a browser? :-) – paxdiablo Feb 01 '11 at 03:12
  • @paxdiablo: No, I'm aware that there are other implementations. That's why I said "at least in most browser implementations". – icktoofay Feb 01 '11 at 03:13
  • icktoofay's solution is correct. You're in charge of the compiler in this scenario so I would have it generate continuations and implement sleeping via `setTimeout`. – ide Feb 01 '11 at 03:14
2

Sounds to me like you want to take a block loop

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

and turn it into

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

Also you can take a for loop

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

and turn it into

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

Basically turn your loops into recursive calls then replace your sleeps with asynchrous recursive calls.

In a loop you need to physically block to slow down the step. In recursion you can delay the call to the next recursive function.

Raynos
  • 166,823
  • 56
  • 351
  • 396
1

The only real and reasonable way to implement sleep() in JavaScript (at least in the browser environment) is to use setTimeout. Just process your compiled instructions one by one, and then take a break when you encounter the sleep instruction:

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();
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
0

If you just want to call a function in X milliseconds you can use setTimeout, but you knew that.

You can hack things together using Date and 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

However you are totally freezing the current thread for a possible long period of time. I think you would basically be stopping all javscript action on the page for X milliseconds, which would be very annoying if the time is greater than 300ms.

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

If you give us a little more context we can probably be more helpful. Sleep is usually used in multithreaded scenarios in other languages, which is exactly why is was left out of javascript. What features do you need in your compiler? :D

Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157