-3

This is a duplicate question. It has been asked many times before, with dozens of answers, some of them rated very highly. Unfortunately, as far as I have been able to tell, every single one of those answers is a variant of "You don't, it's bad programming practice. Use setTimeout instead".

This is Not. An. Answer!

There are some use cases - rare but they exist - where you might want the entire page's execution to halt for a second or two, and I find it very frustrating that nobody seems interested in answering the actual question. (have a look at the comments here for some examples).

I am sure it's possible to halt javascript executing; for instance, if I use firebug to insert a breakpoint, then the execution stops when it hits that point. So, firebug can do it. Is there some way that the program can halt execution of the current thread until some timeout occurs?

Just some thoughts: How does firebug do it? Is there some browser-specific method? Is it possible to trigger a stop, without specifying a timeout to continue? Could I programmatically insert a breakpoint, or remove one? Could I get a closure representing the current thread to pass to setTimeout?

I don't have a specific use case in mind; I am just looking for advise from someone who knows the browser/javascript design better than me, as to how this can most effectively be done.

So far, I have come up with only one solution:

endtime=Date.now()+1000;
while(Date.now() < endtime)
    $.ajax(window.location.origin,{'async':false});

This appears to work. The problem with it is, it makes hundreds of excess requests. I would replace the location.origin with something like mysite/sleep?delay=X and write a server side script to provide the delay, which would but it down to one, but the whole thing still seems really hacky. There must be a better way to do this! How does the jquery.ajax function manage it? Or is there a busy-wait buried in it somewhere?

The following do not answer the question and will be downvoted, just because I am sick of seeing pages of answers that completely ignore the question in their rush to rant on the evils of sleep:

  • Sleep is evil, and you should do anything it takes to avoid needing it.
  • Refactor your code so that you can use setTimeout to delay execution.
  • Busy-wait (because it doesn't stop execution for the duration of the sleep).
  • Refactor your code to use deferred/promise semantics.
Community
  • 1
  • 1
Benubird
  • 18,551
  • 27
  • 90
  • 141
  • 1
    the jQuery ajax function does it using the sync option of the xhr object, so it isn't handled by javascript at all, instead it's handled by a browser api similar to an alert prompt or confirm. – Kevin B Jan 29 '15 at 15:51
  • possible duplicate of [What do I do if I want a JavaScript version of sleep()?](http://stackoverflow.com/questions/951021/what-do-i-do-if-i-want-a-javascript-version-of-sleep) – MatthewG Jan 29 '15 at 15:52
  • 1
    The only way to do this with javascript alone is to have a while or for loop running testing the dateTime. Note however that most modern browsers will kill such a loop after n seconds. – Kevin B Jan 29 '15 at 15:53
  • 1
    So lets get this straight - you've enumerated the 4 *right* answers to this question - you want the *wrong* answer? Hows that going to help anyone else in the future? Oh and good luck avoiding the browser's "A script is running slowly blah blah blah blah" message. – Jamiec Jan 29 '15 at 15:53
  • "if I use firebug to insert a breakpoint, then the execution stops when it hits that point." how do you remove the breakpoint if javascript is halted? (if it's even possible to add/remove breakpoints from javascript, i doubt it) – Kevin B Jan 29 '15 at 15:55
  • 2
    @KevinB Removing breakpoints through JavaScript is by far the most ridiculous thing I've heard. JavaScript itself isn't aware of breakpoints just as C# isn't aware of the ones in Visual Studio. This whole question is ridiculous. – Alternatex Jan 29 '15 at 15:58
  • @Alternatex Right, but even if it were possible, it clearly wouldn't solve his problem because he wouldn't be able to instruct it to bypass or remove the breakpoint, because javascript is halted. – Kevin B Jan 29 '15 at 15:59
  • @KevinB I'd sum up the idea as: paradoxical. – Alternatex Jan 29 '15 at 16:01
  • Another question, this is an XY Problem - what makes you *think* you actually need a sleep whereas (as you pointed out) its been proven time and time again that you just shouldn't do that in Javascript? – Jamiec Jan 29 '15 at 16:06
  • @Jamiec The specific case that prompted this question, is I want to simulate for debugging purposes what happens if the processing time of the script changes a little. i.e. I have a number of events being triggered that could potentially affect the same object, what happens if one of them takes a little more time to execute than expected? If the order in which they complete shifts slightly? But, mostly it's just for interest. – Benubird Jan 30 '15 at 08:17

2 Answers2

0

You should never do this, it's a bad idea...

... because the browser has been, traditionally, single-threaded. Sleeping freezes the UI as well as the script.

However, now that we have web workers and the like, that's not the case. You probably don't need a sleep, but having a worker busy-wait won't freeze the UI. Depending on just how much you want to freeze a particular thread, I've seen people use:

endtime = Date.now()+1000;
while (Date.now() < endtime)

or, curiously (this was in an older but corporate-sponsored analytics library):

endtime = new Date().getTime() + 1000;
while (new Date().getTime() < endtime)

which is probably slower. If you're running a busy wait, that doesn't necessarily matter, and allocating objects probably just burns memory and GC time.

Code using promises or timeouts tends to be more modular, but harder to read (especially when you first learn async techniques). That's not an excuse for not using it, as there are definite advantages, but maybe you need everything to stay synchronous for some reason.

If you have a debugger running and want some chunk of code to pause itself (very useful when you have a bunch of nested callbacks), you can use:

function foo() {
    do.someStuff();
    debugger;
    do.otherStuff();
}

The browser should pause execution at the debugger statement. The debugger can almost always pause execution, because it is in control of the VM running the code; it can just tell the VM to stop running, and that ought to happen. You can't get quite to that level from a script, but if you take source as text (perhaps from a require.js plugin), you can modify it on the fly to include debugger statements, thus "programmatically inserting breakpoints." Bear in mind that they will only take effect when the debugger is already open, though.

To capture the state of a "thread" and persist it for later use, you may want to look into some of the more complicated functional programming concepts, particularly monads. These allow you to wrap a start value in a chain of functions, which modify it as they go, but always in the same way. You could either keep simple state (in some object), or record and reproduce everything the "thread" may have done by wrapping functions in functions. There will be performance implications, but you can pick up the last function later and call it, and you should be able to reproduce everything the thread may have done.

Those are all fairly complicated and specific-use solutions to avoid just deferring things idiomatically, but if you hypothetically need them, they could be useful.

ssube
  • 47,010
  • 7
  • 103
  • 140
0

No, it is not possible to implement a sleep in javascript in the traditional sense, as it is a single-threaded event based model. The act of sleeping this thread will lock up the browser it is running in and the user is presented with a message either telling them the browser has stopped responding (IE) or allowing them to abort the currently running code (Firefox).

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Browser threading has changed significantly in recent times, with web workers and the like (which should be implemented as individual threads). – ssube Jan 29 '15 at 16:08
  • @ssube - Im not sure that fact changes this answer particularly. You can spawn something on a background thread using workers, but you still cant/shouldnt sleep the UI thread – Jamiec Jan 29 '15 at 16:10
  • A busy loop in a worker shouldn't freeze the UI. It's still much better to defer things properly, but the simple answer of "no, it will freeze your browser" now has some caveats. – ssube Jan 29 '15 at 16:12