Reputation: 1618
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.
Upvotes: 2
Views: 3754
Reputation: 140152
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();
Upvotes: 1
Reputation: 129139
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 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();
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.
Upvotes: 4
Reputation: 169531
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.
Upvotes: 2
Reputation: 57988
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
Upvotes: 5
Reputation: 41259
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;
}
}
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
Upvotes: 0