What is the JavaScript version of sleep()?
Asked Answered
F

95

3778

Is there a better way to engineer a sleep in JavaScript than the following pausecomp function (taken from here)?

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

This is not a duplicate of Sleep in JavaScript - delay between actions; I want a real sleep in the middle of a function, and not a delay before a piece of code executes.

Farber answered 4/6, 2009 at 14:41 Comment(11)
This is a horrible solution - you're going to be chewing up processing cycles while doing nothing.Nondisjunction
The only purpose for a sleep is polling or waiting for a callback - setInterval and setTimeout do both better than this.Marrymars
Probably you can do what you want with continuation passing style in JavaScript. Take a look at this article.Fefeal
Possible duplicate of Execute script after specific delay using JavaScriptBraces
It is amazing to see people saying no without understanding what the OP wants. There are cases that you want a real sleep. I am now needing a real sleep to test the browsers behaviour of posting and receiving message between the top window and the iframe. Keeping it busy with while seems the only way.Bipartite
I wanted sleep() to time an animation. (I know there are better ways...) The code the questioner presents will not work for me in Chrome, because rather than updating the DOM as soon as the modification is made in script, the browser waits until the code finishes executing before making any DOM updates, so the script waits the sum of all the delays, and then applies all the DOM updates at once.Candi
@DevsloveZenUML and designers and developers of browser environment decided for the sake of users that you shall NOT have your wish because giving someone explicit ability to block entire page in async application is insane.Rora
@AriFordsham you shouldn't use sleep() for timing an animation in any programming language.Disharmony
I prefer to keep consistency with unix and use sleep in seconds instead of milliseconds... (s) => new Promise((r) => setTimeout(r, 1000 * s | 0))Chouest
@17 of 26 - No, what op wants is a sleep like that possible in a multithreaded/multiprocess environment. A sleep in such an environment (like a native OS application) does not waste cycles. But javascript isn't multi threaded so it's not possible. True, Op's current solution wastes cycles but that's why he's even asking this question - he wants a better anser. Answers that use Promises aren't any better than using settimeout btw.Benzofuran
Note: Since Node 16 you can simply import { setTimeout } from 'timers/promises' and await setTimeout(2000)Dam
H
5351

2017 — 2021 update

Since 2009 when this question was asked, JavaScript has evolved significantly. All other answers are now obsolete or overly complicated. Here is the current best practice:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

Or as a one-liner:

await new Promise(r => setTimeout(r, 2000));

As a function:

const sleep = ms => new Promise(r => setTimeout(r, ms));

or in Typescript:

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

use it as:

await sleep(<duration>);

Demo:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
    for (let i = 0; i < 5; i++) {
        console.log(`Waiting ${i} seconds...`);
        await sleep(i * 1000);
    }
    console.log('Done');
}

demo();

Note that,

  1. await can only be executed in functions prefixed with the async keyword, or at the top level of your script in an increasing number of environments.
  2. await only pauses the current async function. This means it does not block the execution of the rest of the script, which is what you want in the vast majority of the cases. If you do want a blocking construct, see this answer using Atomics.wait, but note that most browsers will not allow it on the browser's main thread.

Two new JavaScript features (as of 2017) helped write this "sleep" function:

Compatibility

If for some reason you're using Node older than 7 (which reached end of life in 2017), or are targeting old browsers, async/await can still be used via Babel (a tool that will transpile JavaScript + new features into plain old JavaScript), with the transform-async-to-generator plugin.

Heartsease answered 7/10, 2016 at 9:44 Comment(33)
Great stuff here. I wonder, how does this affects or relates with the modern browsers "active" / "inactive" states after JS calls the "sleep" mode? Can the browser block the sleep as expected for general JS, to recall later when becomes "active", or does it have a different behavior?Mc
What is the current browser support for this? I wouldn't consider the previous solutions to be "obsolete" until this solution is supported by the vast majority of browsers, or at least all of the common ones. On the contrary, I would consider this solution interesting but unusable/impractical until it has widespread support.Shifty
@AlvinThompson: the majority of modern web development uses transpilers, so native browser support matters less than cleaner and more future-proof code. Anyway, see caniuse.Heartsease
While Promises can be polyfilled, arrow functions cannot. This is not a viable solution for those having to support IE.Trictrac
@Trictrac - the transpiler handles arrow functions as well as async/await (which would cause IE to vomit blood anyway)Sidewinder
Google Apps Script returns Syntax error at the line where the sleep function is defined. (in Chrome 59.0.3071.115 (Official Build) (32-bit))Yetah
oneliner await new Promise(r => setTimeout(() => r(), 2000));Zinnia
Oneliner for the function declaration: const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))Achieve
All other answers are now obsolete or overly complicated, it really is a matter of taste. Some developers will favor using .then chaining or a callback, I don't see anything complicated with that...Hydr
this is the perfect JS solution.. Other solutions are either outdated or not JavaScript-ly.Brickle
@Uciebila: if you await sleep at some point in the loop, the loop will wait the specified amount, then continue looping. Sample code.Heartsease
No matter what the syntax sugar might be, the mechanism underneath it all is still just a setTimeout()Randallrandan
Sure wish I could just call the shell's "sleep 5" instead of doing all this research, alas #1880698 is also complicated.Husk
Since now, new promisified setTimeout() is available in node 16+. import { setTimeout } from 'timers/promises'; await setTimeout(5000) nodejs.medium.com/node-js-16-available-now-7f5099a97e70Walhalla
So something I've noticed with Firefox is that you have to use actual function notation (or whatever it's called) otherwise it resolves instantly... or something: await new Promise((r) => { setTimeout(r, 2000)});Poulin
@AlbertSun: the code from the answer, as well as yours, does log undefined after 2000ms. Can you clarify?Heartsease
I am unable to grok the part where function resolve is defined as calling itself. How does this make sense?Werby
@LoganDevine Do you notice the recursive definition of the resolve function?Werby
@sureshvv: it's not a recursive definition. The first resolve is the parameter name, the second is a function call. See the executor docs.Heartsease
@DanDascalescu OK.. I understand. The Promise has to be instantiated with the resolve and reject functions which get invoked as and when the task is complete.Werby
@Dan Dascalescu Does this sleep function clear the timeout at the end?Fechter
this doesn't work in the case of: click a button on a website -> wait 2 seconds -> click another button on the target website. how can one do this?Terrigenous
actually use async function <name>(parameters) then using await functionname() worked for me. Thanks.Islaen
Honestly surprised this isn't somehow a language feature yet in 2022, in C# you can just do await Task.Delay(5000);...Sirajuddaula
I'd recommend using Rust-like syntax await new Promise((_) => setTimeout(_, 2000)); to make it clear that the function argument is not important here.Arabian
@MikkoRantalainen: interesting point, but I find resolve as the argument clarifies what the argument is, while _ is opaque.Heartsease
I don't understand how this is the accepted solution. The answer would seem to be you can't do a main execution blocking sleep without something like OP's while loop (and it makes sense JS wouldn't let you do this). This answer and others like it which use async/await are the exact same thing as setTimeout.Theurer
@Theurer setTimeout() is the only variant that works with all browsers and in all situations. You cannot use await in top level script in older browsers: caniuse.com/mdn-javascript_operators_await_top_levelArabian
So, which of these variants can I use in a non-async function?Hesitancy
This isn't a solution for "real sleep in the middle of a [synchronous] function" AT ALL! Another fine example for a half baked JavaScript "solution": The async/await stuff always turns old synchronous code into a new callback based model - even if the "Promise/then" syntactic sugar is used to obfuscate that fact in the examples. This makes it absolutely useless for any scenario where you have existing synchronous code, e.g. functions that are required to return a result (not just a Promise).Diverticulitis
I had problems using "return new Promise(resolve => setTimeout(resolve, ms));", by triggering the "sleep(ms)" function again before the time has been completed, the sleep() function simply had its waiting time reduced. To solve this problem, I added a timeout reset. Code: var sleepSetTimeout_ctrl; function sleep(ms) {clearInterval(sleepSetTimeout_ctrl); return new Promise(resolve => sleepSetTimeout_ctrl = setTimeout(resolve, ms));}Mitis
@Mitis I'm curious about your issue. I can't seem to reproduce it. Also why clearInterval() instead of clearTimeout()?Dm
@MarkJohnson, hello, I found this: "It's worth noting that the pool of IDs used by setInterval() and setTimeout() are shared, which means you can technically use clearInterval() and clearTimeout() interchangeably. However, for clarity, you should avoid doing so." developer.mozilla.org/en-US/docs/Web/API/clearInterval - So feel free to edit whatever is necessary, thanks.Mitis
G
868

(See the updated answer for 2016)

I think it's perfectly reasonable to want to perform an action, wait, and then perform another action. If you are used to writing in multi-threaded languages, you probably have the idea of yielding execution for a set amount of time until your thread wakes up.

The issue here is that JavaScript is a single-thread event-based model. While in a specific case, it might be nice to have the whole engine wait for a few seconds, in general it is bad practice. Suppose I wanted to make use of your functions while writing my own? When I called your method, my methods would all freeze up. If JavaScript could somehow preserve your function's execution context, store it somewhere, then bring it back and continue later, then sleep could happen, but that would basically be threading.

So you are pretty much stuck with what others have suggested -- you'll need to break your code up into multiple functions.

Your question is a bit of a false choice, then. There is no way to sleep in the way you want, nor should you pursue the solution you suggest.

Gizmo answered 4/6, 2009 at 14:41 Comment(4)
This is not a correct answer at all. If Javascript does not have a sleep function, it is only because ECMAScript does not require it. It is a design choice by the body responsible for the design of Javascript. It could have been made that the Javascript run time waits a given amount of time before running the next line of code, but it was chosen not to.Villosity
A sleep can be perfectly implemented in JavaScript allbeit not with real-time precision. After all it is an event based system. If async calls are completed an event is triggered. I see no reason why the same can't be possible when a sleep() is issued after which control is returned to the browser until the sleeping is over, returning control to the calling function. And yes, I also agree that sometimes sleeping is handy especially when developers BEFORE you screwed up the design so badly that YOU have no other way out besides completely refactoring for which you have no timeWhyte
Try Hypnotic, which follows this idea: coolwanglu.github.io/hypnotic/web/demo.htmlReconstitute
I agree why sleep() isn't possible in JS, and that most of the time there are better ways to do things. But I'd still consider the way the engine ties all things up to be a design flaw; there's no reason the language couldn't have a sleep() function limited to a specific script, page, or function without the engine clobbering the CPU and freezing the app like a maniac. It's 2015 and you shouldn't be able to crash an entire web browser with while(1). We have Flash for things like that.Gerrit
B
813

In JavaScript, I rewrite every function so that it can end as soon as possible. You want the browser back in control so it can make your DOM changes.

Every time I've wanted a sleep in the middle of my function, I refactored to use a setTimeout().

Edit

The infamous sleep, or delay, function within any language is much debated. Some will say that there should always be a signal or callback to fire a given functionality, others will argue that sometimes an arbitrary moment of delay is useful. I say that to each their own and one rule can never dictate anything in this industry.

Writing a sleep function is simple and made even more usable with JavaScript Promises:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

If you are inside an async function you can do a proper await step with the above definition of sleep():

// Available inside async functions:
await sleep(500);

// Do something after the sleep…
Blavatsky answered 4/6, 2009 at 14:41 Comment(25)
this solution doesn't work if you have any state variables. If the function you're trying to sleep has any parameters. For example, how can one do fuction foobar(el){ setTimeout(foobar_cont(el),5000); } ??? I haven't figured that out yet.Merovingian
By way of closure. function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }Bondsman
ok, and what if the code is not intended to be used in a webpage?Gradatim
@chaos: the function foobar_con takes the value of el at the moment of invocation of function foobar_con, but not unfortunately of the function foobar. Good example is a loop where el is changing: all the delayed function invocations of foobar_con will be with the maximal value of el.Bouffe
@EugenioMiró if the code is not intended to be used in a webpage, have the host's object model implement a sleep method. -- I think the question is geared towards the DOM which is exposed to javascript running on web pages.Swagger
@Nosredna yes, we understand how to make async calls, this doesn't help us sleep(). I want my calls to be made in a certain order, and to have the data back in a certain order. I'm 5 levels deep in a for loop. I want to BLOCK execution. A true sleep method would not "slow down the browser", sleep hands control back to the browser and any other threads that want CPU time while it is still blocking.Swagger
@Tim loop-safe version: for(i=0; i<5; i++) { (function(i) { setTimeout(function() { console.log(i); }, 1000*i); })(i); }Sices
@Morg sorry to disagree with you, I need a solution like this in an environment different than an webpage, please, if you don't like my comment please skip it, I come here to find answers not to read comments like yours. Thanks.Gradatim
@EugenioMiró ; my bad, I probably used the wrong words. Your question is unrelated to the question that was answered here, trying to extend the scope by asking a question in the comments is a bad idea, you should create a new question about node.js or w/e server-side js technology you're using in order to get a real answer.Lossa
ok @Morg, you're right, but as I saw the title was related to javascript and sleep I though it was not only a solution for a web page, I could ask something by myself instead of asking in a comment. Thanks for your suggestion.Gradatim
How would one approach the following cases: 1. During testing the developer wants to simulate that clicking a button calls a process that takes real long and requirements do not allow to either change the way the process is called or to call it asynchronously 2. After clicking a button, some changes happen on the page (like a "please wait..." message that the user will randomly see depending on how busy is the server at the moment but right now the developer wants to visually test the message simulating the server is busy.Otho
good comment Jelgab, you can tell you are a developer. In case someone want's to block the browser on an ajax call, it would be so simple to switch off async on that call: $.ajax({ 'async': false });Shook
Try this almost answer: Hypnotic. coolwanglu.github.io/hypnotic/web/demo.htmlReconstitute
@Tezcat I'm making a .html (no hosting) but sadly, all the familiars I send them to use Chrome ;(Umber
To call functions with parameters using the same code above use for example: foobar_cont_2.bind(this, "value")) to call the function foobar_cont_2(xXx)Borchers
The function assigned to the setTimeout is put onto an event queue. JavaScript is inherently single-threaded. If there’s at least one event on the queue that’s eligible to “fire” (like a 3000ms timeout that was set 4000ms ago), the "javascript VM" will pick one and call its handler (function callback). The point is that the actual call will unlikely be precisely when you requested it (say 3000 milliseconds later), it might be 3001, 3002 or even quite a bit later depending on number and nature of other events on the queue, & the duration of their callbacksAssailant
am I the only one to notice the sleep function is identical to just using setTimeout (minus the reversed arguments) ??Republican
@Republican the original answer just referred to setTimeout and is ok, because it's just an opinion. But the edit misdirects the reader to think that there is a equiv sleep, which is just a call to setTimeout... it's a bad joke really because it wastes ppl's time in reading and understanding... essentially nothing.Synonymous
True (synchronous) sleep is useful in testing, e.g. to simulate a long-running JS task. Many eventing bugs arise due to heavy JS tasks (e.g. backend requests with large payloads that need processing or unbatched processing on very large pages). Synchronous sleep is useful for testing + repro in such cases.Should never run in production code, but far from useless.Questioning
setTimeout doesnt SLEEP in the middle of your function as you've stated. Your function continues executing. Everything else inside the setTimeout will get executed later on.Nunn
@MemetOlsen You have to put the rest of your code inside the callback, or use async/await if available.Took
@Took sure, let me just go ahead and put everything else, including the methods that get called after the current method, inside the callback.. And, where were you 6 years ago when I needed async/await? Oh wait, it didn't exist back thenNunn
It's possible. Many JavaScript architectures work like this where there is a bootstrapping function and everything else goes in the callback. I understand that some don't; I'm just pointing out that that's how promises with callbacks work.Took
Async/await is sugar on top of the same -- it does the same thing as what I am suggesting, but with an easier syntax.Took
const sleep = (ms) => new Promise(r => setTimeout(r, ms));Shriver
E
345

In Firebug (and probably other JavaScript consoles), nothing happen after hitting enter, only after the sleep duration specified (...)

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}

Example of use:

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ 
        /* Do nothing */ 
    }
}

function sleepThenAct(){
    sleepFor(2000);
    console.log("Hello, JavaScript sleep!");
}

sleepThenAct()

Note: Only for debugging and development

Enright answered 4/6, 2009 at 14:41 Comment(16)
This is not an answer. It's exactly the same as the code in the question, except slightly shorter.Hectocotylus
github.com/JDMcKinstry/JavaScript-Delay-Method/blob/master/…Bullnose
Busy waiting, really? In JS? For seconds? If I catch a website doing this, it will be blocked.Wichern
@Wichern That's why it says only for debug/dev... rolleyesViniferous
@Hectocotylus That's one of the reasons why I upvoted it. I find hilarious that he optimized his busy waiting loopViniferous
@Viniferous I'd be hard pressed to come up with an example of this technique ever being the correct way (or even direction) to solve a problem, regardless if dev or prod.Wichern
@Wichern that's true, it's so tricky to come up with a proper example that it probably deserves its own question!Viniferous
@Wichern it's not tricky at all. As Kee said, it's useful for testing. If you just want to run C after B after A, using promises or callbacks leads you straight to hell. I use it to wait for exec to finish doing something. It means that I can write utility functions and call them as part of a simple script, instead of putting whole chunks of code in callbacks.Expensive
NEVER DO THIS. This will make the CPU to hit 100% on the core that it executes and will block it.Ed
This is useful, and perhaps the ONLY way to sleep, within a command-line javascript application, because async/await is not helpful.Aneroidograph
The solution is not good, but in some places async/await it's not responsive unfortunately, and we have to use it mandatorily.Bloodcurdling
This actually solves my issue, because that's exactly what I need: busy wait for debug purposes. I can't use await, I don't know why, it doesn't compile. I'm not a js expert, so I better just use this code, thanks!Interpellate
Why bother with the 'overhead' of a function call when you can get crisp, main thread blocking with this one-liner: for (let e = performance.now() + 2000; performance.now() < e; ) {}Georgiageorgian
I'm upvoting this one because, well for my use case, and actually only for test/dev, I really want a blocking sleep/wait ... people here commenting that "this is not good" are overlooking use cases where it is good :-)Tureen
This answered saved my night! The other answers are not waiting if you're in console. In my case, i needed to send 2k xhr with some delay in between to avoid the ban and scrape the target efficiently... This is the only answer that helpedRollet
I'm using this in a QML (5.15) app. None of the other solutions worked for me, but this one did.Amoeba
P
205

I agree with the other posters. A busy sleep is just a bad idea.

However, setTimeout does not hold up execution. It executes the next line of the function immediately after the timeout is SET, not after the timeout expires, so that does not accomplish the same task that a sleep would accomplish.

The way to do it is to breakdown your function into before and after parts.

function doStuff()
{
  // Do some things
  setTimeout(continueExecution, 10000) // Wait ten seconds before continuing
}

function continueExecution()
{
   // Finish doing things after the pause
}

Make sure your function names still accurately describe what each piece is doing (i.e., GatherInputThenWait and CheckInput, rather than funcPart1 and funcPart2)

This method achieves the purpose of not executing the lines of code you decide until after your timeout, while still returning control back to the client PC to execute whatever else it has queued up.

As pointed out in the comments this will absolutely not work in a loop. You could do some fancy (ugly) hacking to make it work in a loop, but in general that will just make for disastrous spaghetti code.

Privilege answered 4/6, 2009 at 14:41 Comment(10)
Yeah. Where this gets tricky is when you have a loop, or a nested loop even. You have to abandon your for loops and have counters instead.Serapis
Touché. I mean, it would still be possible, but ugly and hackish in that case. You could also use some static boolean state variables, but that's also pretty hackish.Privilege
Any time I have to do it, I comment heavily. JavaScript is meant to run as an event handler, and the pieces are supposed to execute quickly. Making a computation-intensive RIA in JavaScript is certainly possible, but you have to give a lot of time to the browser or your UI gets sluggish. IE, of course, is the worst.Serapis
In the example at the bottom of this blog post, I use variables attached to the function to hold the current progress. dreaminginjavascript.wordpress.com/2008/08/02/…Serapis
-1 for this. Again, this does not answer the question. This is more an answer for a question like "How to execute a function asynchronously" which is very much different from "How to block a code execution".Owe
@Serapis No, you'd use a closure. For example: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); } and for(var X = 0; X < 3;X++) { foo(X); } - the value of X is passed into foo, which then gets reused under the name index when foo_continue is eventually called.Lucid
@Izkata: Have you tried to us this with foo(index) { console.log(c[index-1]); and foo_continue(index) { c[index]=index; }? You will see that the results differ whether you use setTimeout or the fictitious sleep() command.Inexpressive
@Inexpressive Of course it does, because the point of setTimeout() is to prevent the browser from locking up by running the code asychronously. Put the console.log() inside foo_continue() in the setTimeout version and you get the same result.Lucid
This is not an answer to the question. Even if it's a Terrible Idea™ to pause ALL execution, that is what is asked and it's not what this code does.Viniferous
One-liner: setTimeout(() => someSmallBitOfCodeHere(), 10000);Ciri
C
175

For the love of $DEITY please do not make a busy-wait sleep function. setTimeout and setInterval do everything you need.

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

Every two second interval hide text for one second. This shows how to use setInterval and setTimeout to show and hide text each second.

Cheyenne answered 4/6, 2009 at 14:41 Comment(13)
Well not quite everything: setInterval does a much better impression of polling.Marrymars
I sometimes miss a real "sleep", but messing around with setTimeout is still better than actively waiting (like the above while loop). A real sleep function does however not need to freeze the JavaScript engine, but a busy-wait would max out a single CPU core. (And eat up precious battery time of mobile users)Penicillin
What would that piece of code not hold back in the JavaScript engine?Aixenprovence
Unless you need the sleep to be synchronous, in which case this is a completely valid question.Nehru
@Aaron: Since Javascript only supports synchronous sleep by way of hammering the CPU as hard as it possibly can until the sleep duration is over, my sole recommendation for that situation is "redesign until you no longer need synchronous sleep".Bondsman
I think many of us might be forgetting that JavaScript isn't a browser-only language. This dude might be creating a Node command line utility that requires a brief pause without needing to deal with all the variable scoping issues that come with setTimeout.Marden
@PhilLaNasa: If syntactic closure is still scaring one, one seriously needs to buckle down and work through Node 101.Bondsman
@chaos: Completely disagree, closures aren't JS 101. If a novice is looking to write a purely synchronous and simple script, a function like sleep() might come in handy.Marden
@PhilLaNasa: Any context in which closures are not JS 101 needs a full curriculum redesign, stat.Bondsman
My usage is a loop to download hundreds of PDFs from a database whose admin refuses to provide the data in a sensible format. The loop needs a delay between files to ensure little or no overlap.Huberthuberto
@WGroleau: This is a classical example of something people think they need sleep for when they don't. You don't need to busywait-lockup the JS engine, you need to split up your processing across setTimeout.Bondsman
It doesn't "lock it up" It starts all the timeouts as fast as it can, and then after the 1.5 second delay, they all try to run at once and only one actually happens. I DID need a delay between downloads in order to actually get them. What does "split it up" mean? Write separate code for each link instead of running a loop? That would take longer than the twelve hundred clicks I was trying to avoid. What finally worked was changing the delay each time: setTimeout({}, 1500*i++);Huberthuberto
@WGroleau: that's one wonky way to do it. A cleaner one would be for (const url of urls) { await fetch(url); await sleep(1500); }, where this is sleep.Heartsease
G
115

If (like me) you're using JavaScript with Rhino, you can use...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}
Goffer answered 4/6, 2009 at 14:41 Comment(1)
@RousseauAlexandre Incorrect. It is JavaScript using Rhino (at the time, it could equally be Nashorn these days)Goffer
K
79

Use:

await new Promise(resolve => setTimeout(resolve, 2000));

inside an async function.

Katha answered 4/6, 2009 at 14:41 Comment(0)
O
75

If you're using jQuery, someone actually created a "delay" plugin that's nothing more than a wrapper for setTimeout:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

You can then just use it in a row of function calls as expected:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');
Ostensory answered 4/6, 2009 at 14:41 Comment(4)
That's not a bad solution. Keeps context and chainability.Serapis
As of jQuery 1.4, .delay() is part of jQuery (though with semantics different from the above implementation). api.jquery.com/delayHomeopathic
What this question was definitely lacking was a jQuery answer. So glad we got it!Viniferous
If you need a delay between two independent calls, yes. If you need delays to slow down a loop, no.Huberthuberto
W
56

Since Node.js 16+ a new promisified version of setTimeout() is available:

import { setTimeout as sleep } from 'timers/promises'

console.log('Hello!')

await sleep(2000) // 😴 [2 seconds]

console.log('Goodbye, after 2 seconds!')

You can also pass a value with which the promise is fulfilled and also an options (as the second and third arguments). See https://nodejs.org/api/timers.html#timerspromisessettimeoutdelay-value-options.

Thank @kigiri for his comment.

Walhalla answered 4/6, 2009 at 14:41 Comment(3)
Best solution for node, link to the documentation: nodejs.org/api/…Marjana
Making more intuitive you can easily rename it to be called sleep by doing this: import { setTimeout as sleep} from 'timers/promises'; or const { setTimeout: sleep } = require('timers/promises');Redden
@Mercury; I applied your suggestion.Walhalla
F
53

I've searched for a sleep solution too (not for production code, only for development and tests) and found this article:

JavaScript sleep() or wait()

...and here's another article with client-side solutions: JavaScript sleep

Also, when you are calling alert(), your code will be paused too, while the alert is shown -- you need to find a way to not display alert, but get the same effect. :)

Feed answered 4/6, 2009 at 14:41 Comment(1)
I agree, lots of people are saying, "No, don't do this in production code!" Yeah, um, I don't want to. I want to do it in throwaway test code, and as a result I don't want to spend a lot of time making an elegant solution.Sera
O
35

Here you go. As the code says, don't be a bad developer and use this on websites. It's a development utility function.

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}
Otterburn answered 4/6, 2009 at 14:41 Comment(2)
That's basically the same thing as the OP had.Antimacassar
To be more precise, it's what OP asked for an ALTERNATIVE to.Huberthuberto
E
32

Here's a simple solution using a synchronous XMLHttpRequest:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

Contents of file sleep.php:

<?php sleep($_GET['n']);

Now call it with:

sleep(5);

Using an existing server implementation

If you don't have your own application server (for the above PHP script), you could use some online service instead. For instance:

function sleep(n) { 
    var request = new XMLHttpRequest();
    request.open('GET', 'http://httpstat.us/200?sleep=' + n, false);
    request.send(null);
};

sleep(1000);
console.log("one second delay completed.");

Support

About passing false for the asynchronous parameter, mdn notes:

Synchronous requests on the main thread can be easily disruptive to the user experience and should be avoided; in fact, many browsers have deprecated synchronous XHR support on the main thread entirely. Synchronous requests are permitted in Workers.

The actual delay

The number of milliseconds that is passed as argument will be the time that the server waits between receiving the request and sending the response. The delay incurred by transmission and server load will be added to that.

Earthwork answered 4/6, 2009 at 14:41 Comment(3)
@lukad, Use setTimeout() if that works, but if doing so means unraveling 1000 lines of callbacks this might start not looking like a joke.Wellintentioned
Unique approach, though unfortunately non-async XMLHttpRequests are deprecated and will be removed in the future. Which is funny, because that fact is what led me to this question in the first place.Gerrit
nice but do you know if sometime internet is slow or Website ping time is high than it will sleep script for more than argument time. Like if you use sleep(300) and website take time 150 ms for response than javascript code will be sleep for 450ms. and if internet connection is lose by browser it will work for only 0ms. So it is not better solutionDonella
A
31

An inliner:

(async () => await new Promise(resolve => setTimeout(resolve, 500)))();

500 here is the time in milliseconds for which VM will wait before moving to the next line of code.

Bit of tldr;

Basically, when you create a promise, it returns an observable while at creation giving a reference of resolve in a callback meant for handing over data/response once it's available. Here, resolve is called via setTimeOut after 500ms, and till resolve is not executed the outside scope is waiting to proceed further, hence, creating a fake blocking. It's totally different than the non-blocking(or call non-thread-reserving sleep available in other languages), as the thread and most probably the UI and any other ongoing tasks of webpage/node-application will be blocked and the main thread will be exclusively used for awaiting the promise resolution.

Assembly answered 4/6, 2009 at 14:41 Comment(4)
I am unable to grok the part where function resolve is defined as calling itself. How does this make sense?Werby
@Werby check update.Assembly
If want to put in the middle of an async function just use await new Promise(resolve => setTimeout(resolve, sleepMiliseconds))Iatric
This is amazing because it works in synchronous contexts, thanks a lot!X
C
30

2019 Update using Atomics.wait

It should work in Node.js 9.3 or higher.

I needed a pretty accurate timer in Node.js and it works great for that.

However, it seems like there is extremely limited support in browsers.

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

Ran a few 10 second timer benchmarks.

With setTimeout I get a error of up to 7000 microseconds (7 ms).

With Atomics, my error seems to stay under 600 microseconds (0.6 ms)

2020 Update: In Summary

function sleep(millis){ // Need help of a server-side page
  let netMillis = Math.max(millis-5, 0); // Assuming 5 ms overhead
  let xhr = new XMLHttpRequest();
  xhr.open('GET', '/sleep.jsp?millis=' + netMillis + '&rand=' + Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}

function sleepAsync(millis){ // Use only in async function
  let netMillis = Math.max(millis-1, 0); // Assuming 1 ms overhead
  return new Promise((resolve) => {
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // Use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}

async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}

function sleepSyncTest(){
  let source = `${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src = 'data:text/javascript,' + encodeURIComponent(source);
  console.log(src);
  var worker = new Worker(src);
}

of which the server-side page, e.g. sleep.jsp, looks like:

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>
Carolynecarolynn answered 4/6, 2009 at 14:41 Comment(5)
In my opinion better than the accepted solution which can't be implemented as a simple function without async/await in the caller.Pyrogenous
yeah, as long as you are aware that this is blocking and that usually is not a good thingFirstling
Pretty cool, but the fact that this is only really supported in Chrome and Firefox doesn't make it very viable for uses on the web. (Nov 2019)Mvd
This was the answer I was looking for! I had no access to async functions :DCioffi
In the rare situation where blocking is desirable, this is the right solution. I wish I'd seen your answer before I blogged about this thinking I had found a novel solution! In any case, for a detailed explanation, demos and an additional variant of the XHR solution that uses Service Worker: jasonformat.com/javascript-sleepMedora
K
29

First:

Define a function you want to execute like this:

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

Then schedule its execution with the setTimeout method:

setTimeout(alertWorld, 1000)

Note two things

  • the second argument is time in milliseconds
  • as a first argument, you have to pass just the name (reference) of the function, without the parentheses
Kulun answered 4/6, 2009 at 14:41 Comment(1)
The question was to ask a way to sleep in a blocking wy. setTimeout does not do that. It queues in the Macro task Queue.Milline
C
23

A better solution to make things look like what most people want is to use an anonymous function:

alert('start');
var a = 'foo';
// Lots of code
setTimeout(function(){  // Beginning of code that should run AFTER the timeout
    alert(a);
    // Lots more code
}, 5000);  // Put the timeout here

This is probably the closest you'll get to something that simply does what you want.

Note, if you need multiple sleeps this can get ugly in a hurry and you might actually need to rethink your design.

Correlative answered 4/6, 2009 at 14:41 Comment(1)
this is the one that worked for me on desktop browsers and an older mobile phone. The others I tried didn't work on all.Morette
I
22

The shortest solution without any dependencies:

await new Promise(resolve => setTimeout(resolve, 5000));
Ilarrold answered 4/6, 2009 at 14:41 Comment(4)
It doesn't work in IE11. We get syntax error for arrow function.Deflocculate
@Java-DK use await new Promise(function(resolve) { setTimeout(resolve, 5000); });Ilarrold
This is identical to Ahmed Mohammedali's answer (posted first).Feed
@PeterMortensen and it was copied from my different answer I gave at March 2018: https://mcmap.net/q/36254/-how-can-i-wait-in-node-js-javascript-l-need-to-pause-for-a-period-of-timeIlarrold
H
21

The setTimeout is part of the JavaScript asynchronous methods (methods which are starting to execute and their result will be queued sometime in the future to a component called the callback queue, later to be executed)

What you probably want to do is to wrap the setTimeout function within a Promise.

promise example:

const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));

// using native promises
sleep(2000).then(msg => console.log(msg));

async/await example:

const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));

// using async/await in top level
(async function(){
  const msg = await sleep(2000);
  console.log(msg);
})();

Read more about setTimeout

Harter answered 4/6, 2009 at 14:41 Comment(0)
V
20

One-liner using Promises

const wait = t => new Promise(s => setTimeout(s, t, t));

Typescript with Abort Signal

const wait = (x: number, signal?: AbortSignal): Promise<number> => {
  return new Promise((s, f) => {
    const id = setTimeout(s, x, x);
    signal?.addEventListener('abort', () => {
      clearTimeout(id);
      f('AbortError');
    });
  });
};

Demo

const wait = t => new Promise(s => setTimeout(s, t));
// Usage
async function demo() {
    // Count down
    let i = 6;
    while (i--) {
        await wait(1000);
        console.log(i);
    }
    // Sum of numbers 0 to 5 using by delay of 1 second
    const sum = await [...Array(6).keys()].reduce(async (a, b) => {
        a = await a;
        await wait(1000);
        const result = a + b;
        console.log(`${a} + ${b} = ${result}`);
        return result;
    }, Promise.resolve(0));
    console.log("sum", sum);
}
demo();
Vocal answered 4/6, 2009 at 14:41 Comment(1)
The copy/pasta is realMeimeibers
T
14

This answer is for Node 18 and newer versions!

Instead of doing:

await new Promise(resolve => setTimeout(resolve, 2000));

We can now do:

const { setTimeout } = require('timers/promises');
await setTimeout(3000); // sleep 3 seconds
Tetter answered 4/6, 2009 at 14:41 Comment(0)
V
14

I would encapsulate setTimeOut in a Promise for code consistency with other asynchronous tasks: Demo in Fiddle

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {
        setTimeout(function() { resolve(); }, ms);
    }));
}

It is used like this:

sleep(2000).then(function() {
   // Do something
});

It is easy to remember the syntax if you are used to using Promises.

Venge answered 4/6, 2009 at 14:41 Comment(1)
Why is this any better than just using setTimeout(function(){/*do something*/}, 2000);?Trueman
T
13

Most of the answers here are misguided or at the very least outdated. There is no reason JavaScript has to be single threaded, and indeed it isn't. Today all the mainstream browsers support workers. Before this was the case, other JavaScript runtimes like Rhino and Node.js supported multithreading.

'JavaScript is single threaded' is not a valid answer. For example, running a sleep function within a worker would not block any of the code running in the UI thread.

In newer runtimes supporting generators and yield, one could bring similar functionality to the sleep function in a singlethreaded environment:

// This is based on the latest ES6 drafts.
// JavaScript 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// Run code you want to sleep here (omit star if using JavaScript 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // To sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// Resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // Omit .value if using JavaScript 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// Initialize a generator and get first sleep for the recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// Initialize recursive resume function
resume(firstSleep, generator);

This imitation of sleep is different from a true sleep function as it does not block the thread. It is simply sugar on top of JavaScript's current setTimeout function. This functionality type has been implemented in Task.js and should work today in Firefox.

Tnt answered 4/6, 2009 at 14:41 Comment(2)
Workers aren't implemented in IE, at least through version 10. Which currently represents a large amount of users.Gerrit
True, and even then it is not practical to implement sleep using multiple workers. If using Node.js generator functions are already implemented and can be used as described. Mainstream browsers have not all implemented generators as of today.Tnt
C
13

For browsers, I agree that setTimeout and setInterval are the way to go.

But for server-side code, it may require a blocking function (for example, so you can effectively have thread synchronization).

If you're using Node.js and Meteor, you may have run into the limitations of using setTimeout in a fiber. Here is the code for server-side sleep.

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

See: Node.js Fibers, Sleep

Chloroform answered 4/6, 2009 at 14:41 Comment(1)
Server may require a blocking function... I don't see how forcefully blocking Node's only thread and make your entire server unresponsive for several seconds is a good idea, but whateverContemporary
N
12

UPDATE 2022

Just use this code snippet.

await new Promise(resolve => setTimeout(resolve, 2000));
Nievesniflheim answered 4/6, 2009 at 14:41 Comment(0)
C
12

Since Node.js 7.6, you can combine the promisify function from the utils module with setTimeout.

const sleep = require('util').promisify(setTimeout)

General Usage

async function main() {
    console.time("Slept for")
    await sleep(3000)
    console.timeEnd("Slept for")
}

main()

Question Usage

async function asyncGenerator() {
    while (goOn) {
      var fileList = await listFiles(nextPageToken);
      await sleep(3000)
      var parents = await requestParents(fileList);
    }
  }
Crackle answered 4/6, 2009 at 14:41 Comment(0)
T
11

I have searched/googled quite a few webpages on JavaScript sleep/wait... and there is no answer if you want JavaScript to "RUN, DELAY, RUN"... what most people got was either, "RUN, RUN(useless stuff), RUN" or "RUN, RUN + delayed RUN"...

I thought: here is a solution that works... but you have to chop up your running codes...: Yes, I know, this is just an easier to read refactoring... still...

Example 1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setInterval
var i = 0;

function run() {
    // Pieces of codes to run
    if (i == 0){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 1){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } // End interval, stops run
    i++; // Segment of code finished running, next...
}

run();
t = setInterval("run()", 1000);

</script>
</body>
</html>

Example 2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout
var i = 0;

function run() {
    // Pieces of codes to run, can use switch statement
    if (i == 0){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(1000);}
    if (i == 1){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(2000);}
    if (i == 2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(3000);}
    if (i == 3){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()", dur);} // Starts flow control again after 'dur'

run(); // Starts
</script>
</body>
</html>

Example 3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout
var i = 0;

function flow() {
    run(i);
    i++; // Code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i == 5) {clearTimeout(t);} // Stops flow, must be after sleep()
}

function run(segment) {
    // Pieces of codes to run, can use switch statement
    if (segment == 0){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 1){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()", dur);} // Starts flow control again after 'dur'

flow(); // Starts flow
</script>
</body>
</html>

Example 4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); // Stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    // Pieces of codes to run, can use switch statement
    if (segment == 0){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 1){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    i++; // Current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()", dur);} // Starts flow control again after 'dur'

flow(); // Starts flow control for first time...
</script>
</body>
</html>
Tuck answered 4/6, 2009 at 14:41 Comment(1)
Ok, this works with setTimeput, but it's hard to see what's happening. Using setTimeout itself is easier than this.Laplace
D
10

If you want less clunky functions than setTimeout and setInterval, you can wrap them in functions that just reverse the order of the arguments and give them nice names:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript versions:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

You can then use them nicely with anonymous functions:

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

Now it reads easily as "after N milliseconds, ..." (or "every N milliseconds, ...")

Decorous answered 4/6, 2009 at 14:41 Comment(0)
E
10
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
Enlarge answered 4/6, 2009 at 14:41 Comment(3)
It's the same as the real question. Not much point making it the real answer.Binnie
Not a good solution - using this in Selenium's JavaScriptExecutor hangs my Chrome browser about 50% of the time on a 2104 MacBook Pro.Transmittal
An explanation would be in order. What is the idea/gist? How is it different from previous answers?Feed
S
9

I suggest this method for former python developers

const sleep = (time) => {
   return new Promise((resolve) => setTimeout(resolve, Math.ceil(time * 1000)));
};

Usage:

await sleep(10) // for 10 seconds
Soukup answered 4/6, 2009 at 14:41 Comment(0)
E
9

You could do something like this. A sleep method that all functions can inherit:

Function.prototype.sleep = function(delay, ...args) {
    setTimeout(() => this(...args), delay)
}

console.log.sleep(2000, 'Hello, World!!')
Elute answered 4/6, 2009 at 14:41 Comment(2)
My favorite so farAstrea
This is the best solution! No busy-wait, and you can append it to any function to cause a delay before the execution of that function alone.Asturias
S
9

I can understand the purpose of a sleep function if you have to deal with synchronous execution. The setInterval and setTimeout functions create a parallel execution thread which returns the execution sequence back to the main program, which is ineffective if you have to wait for a given result. Of course one may use events and handlers, but in some cases is not what is intended.

Sentry answered 4/6, 2009 at 14:41 Comment(0)
P
8

In the sleep method you can return any then-able object. And not necessarily a new promise.

Example:

const sleep = (t) =>  ({ then: (r) => setTimeout(r, t) })

const someMethod = async () => {

    console.log("hi");
    await sleep(5000)
    console.log("bye");
}

someMethod()
Paperhanger answered 4/6, 2009 at 14:41 Comment(0)
P
8

If you're on Node.js, you can have a look at fibers – a native C extension to node, a kind of-multi-threading simulation.

It allows you to do a real sleep in a way which is blocking execution in a fiber, but it's non-blocking in the main thread and other fibers.

Here's an example fresh from their own readme:

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

– and the results are:

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Perspiration answered 4/6, 2009 at 14:41 Comment(0)
C
8

It can be done using Java's sleep method. I've tested it in Firefox and Internet Explorer and it doesn't lock the computer, chew up resources, or cause endless server hits. It seems like a clean solution to me.

First you have to get Java loaded up on the page and make its methods available. To do that, I did this:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

Then, all you have to do when you want a painless pause in your JavaScript code is:

java.lang.Thread.sleep(xxx)

Where xxx is time in milliseconds. In my case (by way of justification), this was part of back-end order fulfilment at a very small company and I needed to print an invoice that had to be loaded from the server. I did it by loading the invoice (as a webpage) into an iFrame and then printing the iFrame.

Of course, I had to wait until the page was fully loaded before I could print, so the JavaScript code had to pause. I accomplished this by having the invoice page (in the iFrame) change a hidden form field on the parent page with the onLoad event. And the code on the parent page to print the invoice looked like this (irrelevant parts cut for clarity):

var isReady = eval('document.batchForm.ready');
isReady.value = 0;

frames['rpc_frame'].location.href = url;

while (isReady.value == 0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

So the user pushes the button, the script loads the invoice page, waits, checking every quarter second to see if the invoice page is finished loading, and pops up the print dialog for the user to send it to the printer. QED.

Circumjacent answered 4/6, 2009 at 14:41 Comment(2)
Seems quite monstrous soulution when considering the simple thing author wanted to achieve.Sharenshargel
This depends on Java Applets which is deprecated.Disrepair
S
8

You can't do a sleep like that in JavaScript, or, rather, you shouldn't. Running a sleep or a while loop will cause the user's browser to hang until the loop is done.

Use a timer, as specified in the link you referenced.

Sophistry answered 4/6, 2009 at 14:41 Comment(0)
T
7

An old question from 2009. Now in 2015 a new solution is possible with generators defined in ECMAScript 2015 AKA ES6. It was approved in June 2015, but it was implemented in Firefox and Chrome before. Now a sleep function can be made non-busy, non-blocking and nested inside loops and sub-functions without freezing the browser. Only pure JavaScript is needed - no libraries or frameworks.

The program below shows how sleep() and runSleepyTask() can be made. The sleep() function is only a yield statement. It is so simple that it is actually easier to write the yield statement directly in stead of calling sleep(), but then there would be no sleep-word :-) The yield returns a time value to the next() method inside wakeup() and waits. The actual "sleeping" is done in wakeup() using the good old setTimeout(). At callback the the next() method triggers the yield statement to continue, and the "magic" of yield is that all the local variables and the whole call-stack around it is still intact.

Functions that use sleep() or yield must be defined as generators. It is easily done by adding an asterisk to the keyword function*. To execute a generator is a bit trickier. When invoked with the keyword new the generator returns an object that has the next() method, but the body of the generator is not executed (the keyword new is optional and makes no difference). The next() method triggers execution of the generator body until it encounters a yield. The wrapper function runSleepyTask() starts up the ping-pong: next() waits for a yield, and yield waits a next().

Another way to invoke a generator is with keyword yield*, here it works like a simple function call, but it also includes the ability to yield back to next().

This is all demonstrated by the example drawTree(). It draws a tree with leaves on a rotating 3D scene. A tree is drawn as a trunk with 3 parts at the top in different directions. Each part is then drawn as another but smaller tree by calling drawTree() recursively after a short sleep. A very small tree is drawn as only a leaf.

Each leaf has its own life in a separate task started with runSleepyTask(). It is born, grows, sits, fades, falls and dies in growLeaf(). The speed is controlled with sleep(). This demonstrates how easy multitasking can be done.

function* sleep(milliseconds) {yield milliseconds};

function runSleepyTask(task) {
    (function wakeup() {
        var result = task.next();
        if (!result.done) setTimeout(wakeup, result.value);
    })()
}
//////////////// written by Ole Middelboe  /////////////////////////////

pen3D =setup3D();
var taskObject = new drawTree(pen3D.center, 5);
runSleepyTask(taskObject);

function* drawTree(root3D, size) {
    if (size < 2) runSleepyTask(new growLeaf(root3D))
    else {
        pen3D.drawTrunk(root3D, size);
        for (var p of [1, 3, 5]) {
            var part3D = new pen3D.Thing;
            root3D.add(part3D);
            part3D.move(size).turn(p).tilt(1-p/20);
            yield* sleep(50);
            yield* drawTree(part3D, (0.7+p/40)*size);
        }
    }
}

function* growLeaf(stem3D) {
    var leaf3D = pen3D.drawLeaf(stem3D);
    for (var s=0;s++<15;) {yield* sleep(100); leaf3D.scale.multiplyScalar(1.1)}
    yield* sleep( 1000 + 9000*Math.random() );
    for (var c=0;c++<30;) {yield* sleep(200); leaf3D.skin.color.setRGB(c/30, 1-c/40, 0)}
    for (var m=0;m++<90;) {yield* sleep( 50); leaf3D.turn(0.4).tilt(0.3).move(2)}
    leaf3D.visible = false;
}
///////////////////////////////////////////////////////////////////////

function setup3D() {
    var scene, camera, renderer, diretionalLight, pen3D;

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75,
        window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 15, 20);
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    directionalLight = new THREE.DirectionalLight(0xffffaa, 0.7);
    directionalLight.position.set(-1, 2, 1);
    scene.add(directionalLight);
    scene.add(new THREE.AmbientLight(0x9999ff));

    (function render() {
        requestAnimationFrame(render);
        // renderer.setSize( window.innerWidth, window.innerHeight );
        scene.rotateY(10/60/60);
        renderer.render(scene, camera);
    })();

    window.addEventListener(
        'resize',
        function(){
            renderer.setSize( window.innerWidth, window.innerHeight );
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
       },
       false
    );

    pen3D = {
        drawTrunk: function(root, size) {
            // root.skin = skin(0.5, 0.3, 0.2);
            root.add(new THREE.Mesh(new THREE.CylinderGeometry(size/12, size/10, size, 16),
                root.skin).translateY(size/2));
            root.add(new THREE.Mesh(new THREE.SphereGeometry(size/12, 16),
                root.skin).translateY(size));
            return root;
        },

        drawLeaf: function(stem) {
            stem.skin.color.setRGB(0, 1, 0);
            stem.add(new THREE.Mesh(new THREE.CylinderGeometry(0, 0.02, 0.6),
                stem.skin) .rotateX(0.3).translateY(0.3));
            stem.add(new THREE.Mesh(new THREE.CircleGeometry(0.2),
                stem.skin) .rotateX(0.3).translateY(0.4));
            return stem;
        },

        Thing: function() {
            THREE.Object3D.call(this);
            this.skin = new THREE.MeshLambertMaterial({
                color: new THREE.Color(0.5, 0.3, 0.2),
                vertexColors: THREE.FaceColors,
                side: THREE.DoubleSide
            })
        }
    };

    pen3D.Thing.prototype = Object.create(THREE.Object3D.prototype);
    pen3D.Thing.prototype.tilt = pen3D.Thing.prototype.rotateX;
    pen3D.Thing.prototype.turn = pen3D.Thing.prototype.rotateY;
    pen3D.Thing.prototype.move = pen3D.Thing.prototype.translateY;

    pen3D.center = new pen3D.Thing;
    scene.add(pen3D.center);

    return pen3D;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

The 3D stuff is hidden inside setup3D() and is only included to make it less boring than console.log(). Angles are measured in radians by the way.

Tested to work in Firefox and Chrome. Not implemented in Internet Explore and iOS (iPads). Try to run it yourself.

After another pass of the answers I found, that Gabriel Ratener made a similar answer a year ago to What is the JavaScript version of sleep()?.

Toor answered 4/6, 2009 at 14:41 Comment(0)
B
7

One scenario where you might want a sleep() function rather than using setTimeout() is if you have a function responding to a user click that will ultimately end up opening a new i.e. popup window and you have initiated some processing that requires a short period to complete before the popup is displayed. Moving the open window into a closure means that it typically gets blocked by the browser.

Baiss answered 4/6, 2009 at 14:41 Comment(0)
M
7

For the specific case of wanting to space out a set of calls being executed by a loop, you can use something like the code below with prototype. Without prototype, you can substitute the delay function with setTimeout.

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}
Maculate answered 4/6, 2009 at 14:41 Comment(0)
D
4

Naively, you can implement sleep() with a while loop same as the pausecomp function (this is basically the same):

const sleep = (seconds) => {
    const waitUntil = new Date().getTime() + seconds * 1000
    while(new Date().getTime() < waitUntil) {
        // do nothing
    }
}

And you can use the sleep() method like so:

const main = () => {
    const a = 1 + 3

    // Sleep 3 seconds before the next action
    sleep(3)
    const b = a + 4

    // Sleep 4 seconds before the next action
    sleep(4)
    const c = b + 5
}

main()

This is how I imagine you would use the sleep function, and is relatively straightforward to read. I borrowed from the other post Sleep in JavaScript - delay between actions to show how you may have been intending to use it.

Unfortunately, your computer will get warm and all work will be blocked. If running in a browser, the tab will grind to a halt and the user will be unable to interact with the page.

If you restructure your code to be asynchronous, then you can leverage setTimeout() as a sleep function same as the other post.

// define sleep using setTimeout
const sleep = (seconds, callback) => setTimeout(() => callback(), seconds * 1000)

const main = () => {
    const a = 1 + 3
    let b = undefined
    let c = undefined

    // Sleep 3 seconds before the next action
    sleep(3, () => {
        b = a + 4

        // Sleep 4 seconds before the next action
        sleep(4, () => {
            c = b + 5
        })
    })
}

main()

As you said, this isn't what you wanted. I modified the example from Sleep in JavaScript - delay between actions to show why this might be. As you add more actions, you will either need to pull your logic into separate functions or nest your code deeper and deeper (callback hell).

To solve "callback hell", we can define sleep using promises instead:

const sleep = (seconds) => new Promise((resolve => setTimeout(() => resolve(), seconds * 1000)))

const main = () => {
    const a = 1 + 3
    let b = undefined
    let c = undefined

    // Sleep 3 seconds before the next action
    return sleep(3)
        .then(() => {
            b = a + 4

            // Sleep 4 seconds before the next action
            return sleep(4)
        })
        .then(() => {
            c = b + 5
        })
}

main()

Promises can avoid the deep nesting, but still doesn't look like the regular synchronous code that we started with. We want to write code that looks synchronous, but doesn't have any of the downsides.

Let's rewrite our main method again using async/await:

const sleep = (seconds) => new Promise((resolve => setTimeout(() => resolve(), seconds * 1000)))

const main = async () => {
    const a = 1 + 3

    // Sleep 3 seconds before the next action
    await sleep(3)
    const b = a + 4

    // Sleep 4 seconds before the next action
    await sleep(4)
    const c = b + 5
}

main()

With async/await, we can call sleep() almost as if it was a synchronous, blocking function. This solves the problem you may have had with the callback solution from the other post and avoids issues with a long-running loop.

Dragonroot answered 4/6, 2009 at 14:41 Comment(1)
This is the only solution that worked for me. I'm a noob at this, but I suspect that making main() an async so we can call sleep with async may have done the trick.Meridel
S
4

This is a blocking version of sleep. Found it easier to follow during testing activities where you need sequential execution. It can be called like sleep(2000) to sleep the thread for 2 seconds.

function sleep(ms) {
    const now = Date.now();
    const limit = now + ms;
    let execute = true;
    while (execute) {
        if (limit < Date.now()) {
            execute = false;
        }
    }
    return;
  }
Saphena answered 4/6, 2009 at 14:41 Comment(0)
H
4

If you write a sleep function like this

var sleep = function(period, decision, callback){
    var interval = setInterval(function(){
        if (decision()) {
            interval = clearInterval(interval);
            callback();
        }
    }, period);
}

and you have an asynchronous function to call multiple times,

var xhr = function(url, callback){
    // Make an Ajax request
    // Call a callback when the request fulfils
}

And you set up your project like this:

var ready = false;

function xhr1(){
    xhr(url1, function(){ ready = true;});
}
function xhr2(){
    xhr(url2, function(){ ready = true; });
}
function xhr3(){
    xhr(url3, function(){ ready = true; });
}

Then you can do this:

xhr1();
sleep(100, function(){ return done; }, xhr2);
sleep(100, function(){ return done; }, xhr3);
sleep(100, function(){ return done; }, function(){
    // Do more
});

Instead of endless callback indentation like this:

xhr(url1, function(){
    xhr2(url2, function(){
        xhr3(url3, function(){
            // Do more
        });
    });
});
Hotshot answered 4/6, 2009 at 14:41 Comment(0)
M
4

Code taken from this link will not freeze the computer. But it works only in 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);
    }
}
Medallion answered 4/6, 2009 at 14:41 Comment(0)
L
4

First of all - setTimeout and setInterval is what should be used, because of JavaScript's callback-ish nature. If you want to use sleep() it's the control flow or the architecture of your code that is incorrect.

Having said that I suppose I still can help with two implementation of a sleep.

1. Faking synchronous run off the top of my head:

// A module to do that //dual-license: MIT or WTF [you can use it anyhow and leave my nickname in a comment if you want to]
var _ = (function(){
  var queue = [];
  var play = function(){
    var go = queue.shift();
      if(go) {
        if(go.a) {
          go.f();
          play();
        }
        else
        {
          setTimeout(play, go.t);
        }
      }
  }
  return {
    go:function(f){
      queue.push({a:1, f:f});
    },
    sleep:function(t){
      queue.push({a:0, t:t});
    },
    playback:play
  }
})();

[making playback automatic should also be possible]

// Usage

_.go(function(){

  // Your code
  console.log('first');

});

_.sleep(5000);

_.go(function(){

  // Your code
  console.log('next');

});

// This triggers the simulation
_.playback();

2. Real synchronous run

I gave it a lot of thought one day and the only idea I had for a true sleep in JavaScript is technical.

A sleep function would have to be a synchronous Ajax call with a timeout set to the sleep value. That's all and the only way to have a real sleep().

Laplace answered 4/6, 2009 at 14:41 Comment(0)
S
3

If you want code that is usable on all browsers, then use setTimeout() and clearTimeout(). If you're reading this far into answers, you'll probably notice that the accepted answer breaks all JavaScript compilation in Internet Explorer 11, and after using this solution, it seems that 5% of users approximately still use this actively-developed browser and require support.

This has broken almost everything. There are known reports of arrow functions breaking Internet Explorer 11 functionality for the software of Drupal, WordPress, Amazon AWS, IBM, and there's even a dedicated discussion on it on Stack Overflow.

Just check it out...

Browser Compatibility Chart - Arrow Function Expressions

Browser Compatibility Chart - setTimeout

Use setTimeout() and clearTimeout(), and that will do the trick for all browsers...

Working JSBin Demo

var timeout;

function sleep(delay) {
    if(timeout) {
        clearTimeout(timeout);
    }
    timeout = setTimeout(function() {
        myFunction();
    }, delay);
}

console.log("sleep for 1 second");
sleep(1000);

function myFunction() {
    console.log("slept for 1 second!");
}
Subsidize answered 4/6, 2009 at 14:41 Comment(0)
O
3

I prefer this functional style one liner sleep function:

const sleep = (ms) => new Promise((res) => setTimeout(res, ms, ms));

// usage
async function main() {
  console.log("before");
  const t = await sleep(10_000); /* 10 sec */
  console.log("after " + t);
}
main();
Olein answered 4/6, 2009 at 14:41 Comment(1)
This is not sleep funciton. If you call sleep function, it will not wait until time is lapsed, it will execute next instructions immediately.Taxaceous
S
3

In case you really need a sleep() just to test something. But be aware that it'll crash the browser most of the times while debugging - probably that's why you need it anyway. In production mode I'll comment out this function.

function pauseBrowser(millis) {
    var date = Date.now();
    var curDate = null;
    do {
        curDate = Date.now();
    } while (curDate-date < millis);
}

Don't use new Date() in the loop, unless you want to waste memory, processing power, battery and possibly the lifetime of your device.

Secret answered 4/6, 2009 at 14:41 Comment(2)
Your code is virtually the same as the code in the question, which asks if there's a better way of doing this.Bolometer
"This" is relative to each one. The title of the question is: "What do I do if I want a JavaScript version of sleep()?" Use setTimeout or setInterval envolves a different reasoning, what may take more time, so is not always the choice, for instance for a fast debug test. Also, Date.now() is far more memory efficient than new Date() inside a loop, if I'm not wrong.Secret
S
3

I needed a busy-wait for testing purposes. I didn't want to split the code as that would be a lot of work, so a simple for did it for me.

for (var i=0; i<1000000; i++){                  
    // Waiting
}

I didn't see any downside in doing this and it did the trick for me.

Spillman answered 4/6, 2009 at 14:41 Comment(4)
That might be compiled away.Muscolo
Please don't do it this way. This is a blocking sleep call, which means no other javascript can run while your code is hogging the JS thread.Entrance
@SteveMidgley "no other javascript [being able to] run while your code is hogging the JS thread" seems to me to be exactly what the OP wants to do ¯_(ツ)_/¯Leaving
I just ran some tests and it appears even an empty loop will block the browser and CPU (not just JavaScript). And using for loops will almost always execute immediately, regardless of the max value for i, and even with complex math code placed inside. So unless you're only waiting for a few milliseconds, there still seems to be no way to sleep gracefully in JS.Gerrit
A
2

A function to sleep, using a synchronous call to let the OS do it. Use any OS sleep command you like. It is not busy waiting in the sense of using CPU time.

I chose ping on a non-existent address.

const cp = require('child_process');

function sleep(ms)
{
    try{cp.execSync('ping 192.0.2.0 -n 1 -w '+ms);}
    catch(err){}
}

A test to verify it works

console.log(Date.now());
console.log(Date.now());
sleep(10000);
console.log(Date.now());
console.log(Date.now());

And some test results.

1491575275136
1491575275157

(and after 10 seconds)

1491575285075
1491575285076
Angelangela answered 4/6, 2009 at 14:41 Comment(1)
But it doesn't work in a web browser context(?). What context does it work in?Feed
B
2

With await support and bluebird promise:

await bluebird.delay(1000);

This will work like a synchronous sleep(1) of the C language. My favorite solution.

Bulrush answered 4/6, 2009 at 14:41 Comment(1)
If you have await support, you don't need Bluebird.Heartsease
R
2

I know the question is about sleep, and clearly the answer is that it isn't possible. I think a common want for sleep is to handle asynchronous tasks in order; I know I have had to deal with it for sure.

Many cases it may be able to use promises (Ajax requests common use). They let you do asynchronous things in a synchronous manner. There is also handling for success/failure, and they can be chained.

They part of ECMAScript 6, so browser support isn't all there yet, mainly, Internet Explorer does not support them. There is also library called Q for doing promises.

References:

Rittenhouse answered 4/6, 2009 at 14:41 Comment(1)
This should really be a comment, not an answer.Laze
M
2

Embrace the asynchronous nature of JavaScript!

All of the following will return immediately, but have a single place for putting code you want to run after something has happened.

The methods I've outlined here are all for different use cases and are roughly ordered in terms of their complexity.

The different things are as follows:

  • Waiting for some condition to become true
  • Waiting for a set of methods to finish (in any order) before calling a single callback
  • Running a series of asynchronous methods with shared state in a particular order before calling a callback

Wait

Waiting to see if some condition is true is useful where there isn't any accessible callback to tell you when something has finished executing.

This is a pretty basic implementation that assumes that the condition will become true at some point. With a few tweaks it could be expanded to be even more useful (for example, by setting a call limit). (I only wrote this one yesterday!)

function waitFor(predicate, successCallback) {
    setTimeout(function () {
        var result = predicate();
        if (result !== undefined)
            successCallback(result);
        else
            waitFor(predicate, successCallback);
    }, 100);
}

Calling code:

beforeEach(function (done) {
    selectListField('A field');

    waitFor(function () {
        var availableOptions = stores.scrapeStore(optionStore);
        if (availableOptions.length !== 0)
            return availableOptions;
    }, done);
});

Here I'm calling something which loads an Ext JS 'store' and waiting till the store contains something before continuing (the beforeEach is a Jasmine test framework thing).

Wait for several things to complete

I also needed to run a single callback after a load of different methods finished. You can do that like this:

createWaitRunner = function (completionCallback) {
    var callback = completionCallback;
    var completionRecord = [];
    var elements = 0;

    function maybeFinish() {
        var done = completionRecord.every(function (element) {
            return element === true
        });

        if (done)
            callback();
    }

    return {
        getNotifier: function (func) {
            func = func || function (){};

            var index = elements++;
            completionRecord[index] = false;

            return function () {
                func.applyTo(arguments);
                completionRecord[index] = true;
                maybeFinish();
            }
        }
    }
};

Calling code:

var waiter = createWaitRunner(done);

filterList.bindStore = waiter.getNotifier();
includeGrid.reconfigure = waiter.getNotifier(function (store) {
    includeStore = store;
});

excludeGrid.reconfigure = waiter.getNotifier(function (store) {
    excludeStore = store;
});

You either just wait for the notifications or can also wrap other functions which use the values passed to the function. When all the methods are called then done will be run.

Running asynchronous methods in order

I've used a different approach when I had a series of asynchronous methods to call in a row (again in tests). This is somewhat similar to something you can get in the Async library - series does about the same thing and I had a little read of that library first to see if it did what I wanted. I think mine has a nicer API for working with tests though (and it was fun to implement!).

// Provides a context for running asynchronous methods synchronously
// The context just provides a way of sharing bits of state
// Use 'run' to execute the methods.  These should be methods that take a callback and optionally the context as arguments
// Note the callback is provided first, so you have the option of just partially applying your function to the arguments you want
// instead of having to wrap even simple functions in another function

// When adding steps you can supply either just a function or a variable name and a function
// If you supply a variable name then the output of the function (which should be passed into the callback) will be written to the context
createSynchronisedRunner = function (doneFunction) {
    var context = {};

    var currentPosition = 0;
    var steps = [];

    // This is the loop. It is triggered again when each method finishes
    var runNext = function () {
        var step = steps[currentPosition];
        step.func.call(null,
                       function (output) {
                           step.outputHandler(output);
                           currentPosition++;

                           if (currentPosition === steps.length)
                               return;

                           runNext();
                       }, context);
    };

    var api = {};

    api.addStep = function (firstArg, secondArg) {
        var assignOutput;
        var func;

        // Overloads
        if (secondArg === undefined) {
            assignOutput = function () {
            };
            func = firstArg;
        }
        else {
            var propertyName = firstArg;
            assignOutput = function (output) {
                context[propertyName] = output;
            };
            func = secondArg;
        }

        steps.push({
            func: func,
            outputHandler: assignOutput
        });
    };

    api.run = function (completedAllCallback) {
        completedAllCallback = completedAllCallback || function(){};

        var lastStep = steps[steps.length - 1];
        var currentHandler = lastStep.outputHandler;
        lastStep.outputHandler = function (output) {
            currentHandler(output);
            completedAllCallback(context);
            doneFunction();
        };

        runNext();
    };

    // This is to support more flexible use where you use a done function in a different scope to initialisation
    // For example, the done of a test but create in a beforeEach
    api.setDoneCallback = function (done) {
        doneFunction = done;
    };

    return api;
};

Calling code:

beforeAll(function (done) {
    var runner = createSynchronisedRunner(done);
    runner.addStep('attachmentInformation', testEventService.getAttachmentCalled.partiallyApplyTo('cat eating lots of memory.jpg'));
    runner.addStep('attachment', getAttachment.partiallyApplyTo("cat eating lots of memory.jpg"));
    runner.addStep('noAttachment', getAttachment.partiallyApplyTo("somethingElse.jpg"));
    runner.run(function (context) {
        attachment = context.attachment;
        noAttachment = context.noAttachment;
    });
});

PartiallyApplyTo here is basically a renamed version of Douglas Crockford's implementation of Curry. A lot of the stuff I'm working with takes a callback as the final argument so simple calls can be done like this rather than having to wrap everything with an extra function.

Minutiae answered 4/6, 2009 at 14:41 Comment(0)
O
2

If you like an advise to not lose performance. setTimeout is your expected sleep. However, if you want a syntax where code is "divided in middle" by sleep, we can do:

sleep = function(tm, fn){
   window.setTimeout(fn, tm);
}

Then, prepare functions as in the following:

var fnBeforeSleep = function(){

  // All code before sleep

}

var fnAfterSleep = function(){

  // All code after sleep

}

Then:

fnBeforeSleep();
sleep(2000, fnAfterSleep);

// Yep! Syntactically, it is very close to:

fnBeforeSleep();
sleep(2000);
fnAfterSleep();
Oscillograph answered 4/6, 2009 at 14:41 Comment(0)
P
2

You can use a closure call setTimeout() with incrementally larger values.

var items = ['item1', 'item2', 'item3'];

function functionToExecute(item) {
  console.log('function executed for item: ' + item);
}

$.each(items, function (index, item) {
  var timeoutValue = index * 2000;
  setTimeout(function() {
    console.log('waited ' + timeoutValue + ' milliseconds');
    functionToExecute(item);
  }, timeoutValue);
});

Result:

waited 0 milliseconds
function executed for item: item1
waited 2000 milliseconds
function executed for item: item2
waited 4000 milliseconds
function executed for item: item3
Piccard answered 4/6, 2009 at 14:41 Comment(4)
This is a great way to limit the calls to an api before they get chance to cache. (Im my case I was sending a few duplicate postcodes to the google geocode api and caching the result, there were two problems. The loop would have executed so quick that the first api response would still be returning, and google geocode api has a rate limiter to would have just started rejecting requests).Brittaney
tldr; you'll have to do something like tponthieux's answer when working in a loop context. (myArray.forEach or for(i=1; ...Brittaney
We should get this answer voted up as it's useful and offers something different from the millions of other answers on this question.Brittaney
Can you elaborate on "a closure call setTimeout()"? And what is the reason for "incrementally larger values"?Feed
S
1

You can use a combination of Promise and setTimeout:

const sleep = (ms) => {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

Then use an await:

await sleep(3000);

I've purposefully used a longer version of the function to make it easier to understand, but it can be written more concisely:

const sleep = (ms) => {
    return new Promise(resolve => setTimeout(resolve, ms));
}

This will achieve a similar result to sleep() in other languages, as will have little CPU usage.

Superscribe answered 4/6, 2009 at 14:41 Comment(0)
N
1

The currently accepted solution of using async/await and setTimeout is perfect if you need to really wait that many seconds. If you are using it for on-screen animations, however, you should really be using requestAnimationFrame(). This functions very similarly to setTimeout, but the callback is only called when the animation is visible to the user. That means that if you're running an animation on your site and the user switches tabs, the animation will pause and save battery life.

Here's an implementation of the wait method using requestAnimationFrame. It takes in a number of frames and resolves once they have all passed:

const waitFrames = (frames) => 
  new Promise((resolve) => {
    let framesPassed = 0;
    requestAnimationFrame(function loop() {
      if (++framesPassed >= frames) return resolve();
      requestAnimationFrame(loop);
    });
  });
  
// typewriter effect for demonstration
const content = document.querySelector(".content");

async function typeWriter(endText, frames) {
  content.textContent = "";
  for (const letter of endText) {
    content.textContent += letter;
    await waitFrames(frames);
  }
}

typeWriter("Okay. This simple typewriter effect is an example of requestAnimationFrame.", 8);
<p>
  The animation will play below; Try switching tabs and see that   
  the animation pauses.
</p>
<code class="content"></code>

Read more about requestAnimationFrame

Browser support (IE10+)

Noguchi answered 4/6, 2009 at 14:41 Comment(0)
G
1

What is the JavaScript version of sleep()?

This has already been answered in the currently accepted answer:

await new Promise(r => setTimeout(r, 1000));

Two asynchronous functions running simultaneously

It is a good idea to put it inside a function sleep(), and then await sleep().
To use it, a bit of context is needed:

function sleep (ms) { return new Promise(r => setTimeout(r, ms)); }

(async function slowDemo () {
  console.log('Starting slowDemo ...');
  await sleep(2000);
  console.log('slowDemo: TWO seconds later ...');
})();

(async function fastDemo () {
  console.log('Starting fastDemo ...');
  await sleep(500);
  for (let i = 1; i < 6; i++) {
    console.log('fastDemo: ' + (i * 0.5) + ' seconds later ...');
    await sleep(500);
  }
})();
.as-console-wrapper { max-height: 100% !important; top: 0; }

Two asynchronous calls running in sequence – one after the other

But suppose slowDemo produces some result that fastDemo depends upon.
In such a case, slowDemo must run to completion before fastDemo starts:

function sleep (ms) { return new Promise(r => setTimeout(r, ms)); }

(async () => {
  await (async function slowDemo () {
    console.log('Starting slowDemo ...');
    await sleep(2000);
    console.log('slowDemo: TWO seconds later ... completed!');
  })();

  (async function fastDemo () {
    console.log('Starting fastDemo ...');
    await sleep(500);
    let i = -2;
    for (i = 1; i < 5; i++) {
      console.log('fastDemo: ' + (i * 0.5) + ' seconds later ...');
      await sleep(500);
    }
    console.log('fastDemo: ' + (i * 0.5) + ' seconds later. Completed!');
  })();
})();
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ginseng answered 4/6, 2009 at 14:41 Comment(0)
C
1

Using TypeScript:

Here's a quick sleep() implementation that can be awaited. This is as similar as possible to the top answer. It's functionally equivalent, except ms is typed as number for TypeScript.

const sleep = (ms: number) =>
  new Promise((resolve) => setTimeout(resolve, ms));

async function demo() {
  console.log('Taking a break for 2s (2000ms)...');
  await sleep(2000);
  console.log('Two seconds later');
}

demo();

This is it. await sleep(<duration>).

Note that,

  1. await can only be executed in functions prefixed with the async keyword, or at the top level of your script in some environments (e.g., the Chrome DevTools console, or Runkit).
  2. await only pauses the current async function.
Candie answered 4/6, 2009 at 14:41 Comment(0)
G
1

If you really want to block the main thread altogether and keep the event loop from pulling from the event queue, here's a nice way to do that without creating any functions, new Date objects or leaking any variables. I know there's a million answers to this silly question already, but I didn't see anyone using this exact solution. This is for modern browsers only.

Warning: This is not something you would ever put into production. It is just helpful for understanding the browser event loop. It is probably not even useful for any testing. It is not like a normal system sleep function because the JavaScript runtime is still doing work every cycle.

for (let e = performance.now() + 2000; performance.now() < e; ) {}

Used here, the setTimeout callback won't be called until at least two seconds later even though it enters the event queue almost instantly:

setTimeout(function() {
  console.log("timeout finished");
}, 0);

for (let e = performance.now() + 2000; performance.now() < e; ) {}
console.log("haha wait for me first");

You will experience a approximate two second pause and then see:

haha wait for me first
timeout finished

The benefit of using performance.now() over Date.now() is that that the Date object is

subject to both clock skew and adjustment of the system clock. The value of time may not always be monotonically increasing and subsequent values may either decrease or remain the same. *

In general, performance.now() is more suited to measuring differences in time at high accuracy.

Using a for loop has the benefit of letting you set variables local to the block before running. This allows you to do the addition math outside the loop while still being a 'one-liner'. This should hopefully minimize the CPU load of this hot cycle burn.

Georgiageorgian answered 4/6, 2009 at 14:41 Comment(0)
L
1

This will do you the trick.

var reloadAfter = 10; //seconds
var intervalId = setTimeout(function() {
    //code you want to execute after the time waiting
}, reloadAfter * 1000); // 60000 = 60 sec = 1 min
Leila answered 4/6, 2009 at 14:41 Comment(1)
How is this different from previous answers?Feed
C
1

The problem with most solutions here is that they rewind the stack. This can be a big problem in some cases. In this example I show how to use iterators in a different way to simulate real sleep.

In this example the generator is calling its own next(), so once it's going, it's on its own.

var h = a();
h.next().value.r = h; // That's how you run it. It is the best I came up with

// Sleep without breaking the stack!!!
function *a(){
    var obj = {};

    console.log("going to sleep....2s")

    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("woke up");
    console.log("going to sleep no 2....2s")
    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("woke up");
    console.log("going to sleep no 3....2s")

    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("done");
}
Callum answered 4/6, 2009 at 14:41 Comment(0)
T
1

There's a new library, Sequencr.js, that neatly chains functions together with timeouts so you can avoid callback hell.

It turns this:

setTimeout(function(timeout){
    function1();
    setTimeout(function(timeout){
        function2();
        setTimeout(function(timeout){
            function3();
        }, timeout, timeout)
    }, timeout, timeout)
}, 10, 10);

into this:

Sequencr.chain([function1, function2, function3], 10);

And has built-in support for loops that "sleep" between each iteration.

Trueman answered 4/6, 2009 at 14:41 Comment(0)
S
1

To summarize (like it has been said in previous answers):

There is no built-in sleep function in JavaScript. You should use setTimeout or setInterval to achieve a similar effect.

If you really wanted to, you could simulate sleep functionality with a for loop such as the one shown in the original question, but that would make your CPU work like crazy. Inside a Web Worker an alternative solution would be to make a synchronous XMLHttpRequest to a non-responsive IP address and set a proper timeout. This would avoid the CPU utilization problem. Here's a code example:

// Works only inside a web worker

function sleep(milliseconds) {
    var req = new XMLHttpRequest();
    req.open("GET", "http://192.0.2.0/", false);
    req.timeout = milliseconds;
    try {
        req.send();
    } catch (ex) {

    }
}

console.log('Sleeping for 1 second...');
sleep(1000);
console.log('Slept!');

console.log('Sleeping for 5 seconds...')
sleep(5000);
console.log('Slept!');
Shier answered 4/6, 2009 at 14:41 Comment(1)
nice but not possible anymore: ``` Sleeping for 1 second... VM1537 js:17 Uncaught InvalidAccessError: Failed to set the 'timeout' property on 'XMLHttpRequest': Timeouts cannot be set for synchronous requests made from a document.sleep @ VM1537 js:17(anonymous function) @ VM1537 js:26 ```Satang
A
1

A method of an object that needs to use a "sleep" method such as the following:

function SomeObject() {
    this.SomeProperty = "xxx";
    return this;
}
SomeObject.prototype.SomeMethod = function () {
    this.DoSomething1(arg1);
    sleep(500);
    this.DoSomething2(arg1);
}

Can almost be translated to:

function SomeObject() {
    this.SomeProperty = "xxx";
    return this;
}
SomeObject.prototype.SomeMethod = function (arg1) {
    var self = this;
    self.DoSomething1(arg1);
    setTimeout(function () {
        self.DoSomething2(arg1);
    }, 500);
}

The difference is that the operation of "SomeMethod" returns before the operation "DoSomething2" is executed. The caller of "SomeMethod" cannot depend on this. Since the "Sleep" method does not exists, I use the latter method and design my code accordingly.

Astragal answered 4/6, 2009 at 14:41 Comment(0)
T
1

If you want to sleep an anonymous function like one you've created as a handler, I recommend the following:

function()
{
    if (!wait_condition)
    {
        setTimeout(arguments.callee, 100, /* Comma-separated arguments here */);
    }
    // The rest of the function
}

This code says "If the wait condition has not yet been satisfied, call this function again with these arguments." I've used this method to pass in the same arguments to my handlers, effectively making this code a non-polling sleep() (which only works at the start of your function).

Terminal answered 4/6, 2009 at 14:41 Comment(0)
C
0

The main process can be wrapped in an anonymous async function, and then await can be used naturally inside it.

<script>
(async()=>{
  for (let i=0; i<5; i++) {
    console.log(`Waiting ${i} seconds...`)
    await new Promise(r => setTimeout(r, i*1000)) // 👈 sleep
  }
  console.log("done")
})()
</script>
Charley answered 4/6, 2009 at 14:41 Comment(0)
P
0
  1. Add below function in the library file or in the same file where you going to call or need some sleep before process the next task.

    const sleep = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); });

  2. Then you have to call the below sleep function from a async function where you need some sleep before process the next task.

const submitForm = async (values, actions) => { await sleep(1000); // Then other task });

Pinto answered 4/6, 2009 at 14:41 Comment(0)
C
0

A SAFER async sleep with better DX

I use sleep for debugging... and I've forgotten to use await a dozen too many times. Leaving me scratching my head. I forgot to use await while writing the live snippet below... NO MORE!

The sleep function below alerts you if you run it twice in 1 ms. It also supports passing a quite parameter, if you're sure you used await. It does not throw so it should be safe to use as a replacement for sleep(s). Enjoy.

Yes there is a JavaScript version in the live snippet.

// Sleep, with protection against accidentally forgetting to use await
export const sleep = (s: number, quiet?: boolean) => {
  const sleepId = 'SLEEP_' + Date.now()
  const G = globalThis as any
  if (G[sleepId] === true && !quiet) {
    console.error('Did you call sleep without await? use quiet to hide msg.')
  } else {
    G[sleepId] = true
  }
  return new Promise((resolve) => {
    !quiet && setTimeout(() => {
      delete G[sleepId]
    }, 1)
    setTimeout(resolve, (s * 1000) | 0)
  })
}

// Sleep, with protection agains accidentally forgetting to use await
const sleep = (s, quiet) => {
  const sleepId = 'SLEEP_' + Date.now()
  const G = globalThis
  if (G[sleepId] === true && !quiet) {
    console.error('Did you call sleep without await? use quiet to hide msg.')
  } else {
    G[sleepId] = true
  }
  return new Promise((resolve) => {
    !quiet && setTimeout(() => {
      delete G[sleepId]
    }, 1)
    setTimeout(resolve, (s * 1000) | 0)
  })
}

const main = async() => {
  console.log('Sleeping for 1 second...')
  await sleep(1)
  console.log('forgetting to use await...')
  sleep(99)
  sleep(99)
  await sleep(1, true)
  console.log('Happy developer!')
}
main()

In contrast with the admittedly easier to read:

const sleep = (s: number) =>
  new Promise((p) => setTimeout(p, (s * 1000) | 0))
Chouest answered 4/6, 2009 at 14:41 Comment(0)
F
0

JavaScript is a single-threaded execution environment. Every function out there is getting executed by just one thread. Asking for a "sleep" means you want to halt the whole VM instance for those many (milli)seconds, which I don't think is a very realistic ask in the JavaScript world, as not only that particular function, but the rest of all executions suffer if the executing thread is made to sleep.

First of all, it is not possible to actually sleep that thread. You can only try to keep that thread busy by putting into some work doing no thing. However, if you want to only add a delay in some computation(s), put their executions inside a single function context, and let the continuation happen inside a setTimeout (or a Promise, if you prefer) from within that function. If by sleep, you are looking to delay something, otherwise, it's not possible.

Feed answered 4/6, 2009 at 14:41 Comment(0)
H
0

2021+ Update

If you are looking for an alternative to:

let sleep = ms => new Promise(res=>setTimeout(res,ms));

Then use this:

let sleep = async ms => void await Atomics.waitAsync(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms).value;

Note, that as of when this question is posted, it is a Stage 3 proposal. Also, it may require your site to be cross-origin isolated. To see if it works in your browser, (on Stack Overflow) try this:

let sleep = async ms => void await Atomics.waitAsync(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms).value;

void async function() {
  console.log(1);
  await sleep(2000);
  console.log(2);
}()
Hilversum answered 4/6, 2009 at 14:41 Comment(2)
What is the advantage of this method over setTimeout?Ostrogoth
@Ostrogoth it's pricise to less than a millisecond. In browsers setTimeout can be off my 100ms, specially Firefox with high privacy settings.Chouest
N
0

I think the question is great and points out important perspectives and considerations.

With that said, I think the core of the question is in the intention and understanding what developer (you) wants to have controlled.

First, the name sleep is an overloaded naming choice. I.e., "what" is going to be "slept"; and "what" as a developer am I in control of?

In any language-engine, running on any OS process, on any bare-metal-or-hosted system the "developer" is NOT in control (owner) of the OS-shared-resource CPU core(s) [and/or threads] unless they are the writing the OS/Process system itself. CPUs are a time-shared resource, and the currency of work-execution progress are the "cycles" allocated amongst all work to be performed on the system.

As an app/service developer, it is best to consider that I am in control of a workflow-activity-stream managed by a os-process/language-engine. On some systems that means I control a native-os-thread (which likely shares CPU cores), on others it means I control an async-continuation-workflow chain/tree.

In the case of JavaScript, it is the "latter".

So when "sleep" is desired, I am intending to cause my workflow to be "delayed" from execution for some period of time, before it proceeds to execute the next "step" (phase/activity/task) in its workflow.

This is "appropriately" saying that as a developer it is easiest to (think in terms of) model work as a linear-code flow; resorting to compositions of workflows to scale as needed.

Today, in JavaScript, we have the option to design such linear work flows using efficient multi-tasking 1980s actor based continuation architectures (relabeled as modern Futures/Promises/then/await etc).

With that in mind, my answer is not contributing a new technical solution, but rather focusing on the intent and the design perspective within the question itself.

I suggest that any answer begins with thinking about the above concepts and then choosing a NAME (other than sleep) that reminds and suggests what the intention is.

Workflow

  • Choice 1: delayWorkForMs(nMsToDelay)
  • Choice 2: delayAsyncSequenceForMs(msPeriod)
async delayAsyncSequenceForMs(msPeriod) {
  await new Promise(resolve => setTimeout(resolve, msPeriod));
}

Keep in mind that any async function always returns a Promise, and await may only be used within an async function.
(lol, you might ask yourself why...).

  • Consideration 1: do-not use "loops" to BURN UP cpu-cycles.
  • Consideration 2: In the JavaScript model, when inside a non-async function you cannot "delay" (wait for) an "async" workflow's execution (unless you are doing bad things needlessly burning cpu cycles). You can only "delay" code-steps within an "async" function.
    Internally, an "async" function is modelled as a collection of entry-point/continuations at each await keyword. If you are familiar with the backtick interpolation model, you can "think of await" as being conceptually modelled similarly to writing a backquote string like:
  // Conceptualizing, using an interpolation example to illustrate
  // how to think about "await" and "async" functions
  `code${await then-restart-point}more-code${await then-restart-point}`
Nowlin answered 4/6, 2009 at 14:41 Comment(0)
W
0

To keep the main thread busy for some milliseconds:

function wait(ms) {
  const start = performance.now();
  while(performance.now() - start < ms);
}
Watermelon answered 4/6, 2009 at 14:41 Comment(1)
Busy wait? Isn't it already covered by a previous answer?Feed
P
0

I have had this question for a long time and the answer I needed was not exactly what has been provided here. This wait function causes a synchronous wait that does not tie up the CPU.

Function waitForIt makes an Ajax request to anywhere and sets the async flag to false. Function waitF does the same with a frame and function waitD does the same with a div. Ajax takes about 100 ms, frame is about 25, and div is about 1.

The wait function leverages all of these depending on how much time you give it. If it didn't wait long enough then do it again.

I need this when dealing with multiple asynchronous loading elements. Basically for 'wait until this element exists'. You can play with it at https://jsfiddle.net/h2vm29ue/. It just leverages the things that the browser naturally waits for. The longer version, https://jsfiddle.net/5cov1p0z/32/, is more precise.

 function waitForIt() {
     var start = new Date();
     var xhttp = new XMLHttpRequest();
     xhttp.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
            // Doesn't matter
         }
     };
     xhttp.open("GET", "WaitForIt", false);
     xhttp.send();
     var end = new Date();
 }
 //

 function waitF() {
     var start = new Date();
     var ifram = document.createElement('iframe');
     ifram.id = 'ifram';
     ifram.src = '';
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     document.getElementById('timer').appendChild(ifram);
     document.getElementById('timer').removeChild(ifram);
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }


 function waitD() {
     var start = new Date();
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     div.click();
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }

 function wait(time) {
     var start = new Date();
     var end = new Date();
     while ((end - start < time)) {

         if ((time - (end - start)) >= 200) {
             waitForIt();
         } else {
             if ((time - (end - start)) >= 50) {
                 waitF();
             } else {
                 waitD();
             }
         }
         end = new Date();
     }
     return (end - start);
 }
Pike answered 4/6, 2009 at 14:41 Comment(0)
M
0

At server side, you can use the deasync sleep() method, which is natively implemented in C so it can effectively implement a wait effect without blocking the event loop or putting your CPU at 100% of load.

Example:

#!/usr/bin/env node

// Requires `npm install --save deasync`
var sleep = require("deasync").sleep;

sleep(5000);

console.log ("Hello World!!");

But, if you need a pure JavaScript function (for example, to run it at client-side by a browser), I'm sorry to say that I think your pausecomp() function is the only way to approach it and, more than that:

  1. That pauses not only your function but the whole event loop. So no other events will be attended.

  2. It puts your CPU at 100% load.

So, if you need it for a browser script and doesn't want those terrible effects, I must say you should rethink your function in a way:

a). You can recall it (or call a do_the_rest() function) at a timeout. The easier way if you are not expecting any result from your function.

b). Or, if you need to wait for a result, then you should move to using promises (or a callback hell, of course ;-)).

No result expected example:

function myFunc() {

    console.log ("Do some things");

    setTimeout(function doTheRest(){
        console.log ("Do more things...");
    }, 5000);

    // Returns undefined.
};

myFunc();

An example returning a promise (notice it alters your function usage):

function myFunc(someString) {

    return new Promise(function(resolve, reject) {

        var result = [someString];
        result.push("Do some things");

        setTimeout(function(){
            result.push("Do more things...");
            resolve(result.join("\n"));
        }, 5000);
    });
};


// But notice that this approach affect to the function usage...
// (It returns a promise, not actual data):
myFunc("Hello!!").then(function(data){
    console.log(data);
}).catch(function(err){
    console.error(err);
});
Monney answered 4/6, 2009 at 14:41 Comment(0)
C
0

If you really want to pause a script, you can do this:

var milliseconds;
var pretime;
var stage;

function step(time){
  switch(stage){
    case 0:
      //Code before the pause

      pretime=time;
      milliseconds=XXX;
      stage=1;
      break;
    case 1:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=2;
      }
      break;
    case 2:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=3;
      }
      break;
    case 3:
      //Etc...
  }

  Window.requestAnimationFrame(step)
}

step();

This is probably exactly what you want if you use a loop anyway, and you can change it in ways so that you have pseudo-multi-threading, where you have some functions waiting a while and others running normally. I use this all the time for pure JavaScript games.

Cadman answered 4/6, 2009 at 14:41 Comment(0)
P
0

I navigated the solutions for a day, but I am still thinking about how to maintain the chainability in using a callback.

Everyone is familiar with the traditional programming style which is running the code line by line in a synchronised way. SetTimeout uses a callback so the next line does not wait for it to complete. This lets me think how to make it "sync", so as to make a "sleep" function.

Beginning with a simple coroutine:

function coroutine() {
    console.log('coroutine-1:start');
    sleepFor(3000); // Sleep for 3 seconds here
    console.log('coroutine-2:complete');
}

I want to sleep 3 seconds in the middle, but I don't want to dominate the whole flow, so the coroutine must be executed by another thread. I consider the Unity YieldInstruction, and modify the coroutine in the following:

function coroutine1() {
    this.a = 100;
    console.log('coroutine1-1:start');
    return sleepFor(3000).yield; // Sleep for 3 seconds here
    console.log('coroutine1-2:complete');
    this.a++;
}

var c1 = new coroutine1();

Declare the sleepFor prototype:

sleepFor = function(ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?sleepFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    setTimeout(function() {
        new Function(funcArgs, funcBody).apply(context, args);
    }, ms);
    return this;
}

After running the coroutine1 (I tested in Internet Explorer 11 and Chrome 49), you will see it sleep 3 seconds between two console statements. It keeps the codes as pretty as the traditional style.

The tricky bit is in sleepFor routine. It reads the caller function body as string and break it into two parts. Remove the upper part and create another function by lower part. After waiting for the specified number of milliseconds, it calls the created function by applying the original context and arguments. For the original flow, it will end by "return" as usual. For the "yield"? It is used for regular expression matching. It is necessary but no use at all.

It is not 100% perfect at all, but it achieves my jobs at least. I have to mention some limitations in using this piece of codes. As the code is being broken into two parts, the "return" statement must be in outer, instead of in any loop or {}. i.e.

function coroutine3() {
    this.a = 100;
    console.log('coroutine3-1:start');
    if(true) {
        return sleepFor(3000).yield;
    } // <- Raise an exception here
    console.log('coroutine3-2:complete');
    this.a++;
}

The above code must have a problem as the close bracket could not exist individually in the created function. Another limitation is all local variables declared by "var xxx=123" could not carry to the next function. You must use "this.xxx=123" to achieve the same thing. If your function has arguments and they got changes, the modified value also could not carry to the next function.

function coroutine4(x) { // Assume x=abc
    var z = x;
    x = 'def';
    console.log('coroutine4-1:start' + z + x); // z=abc, x=def
    return sleepFor(3000).yield;
    console.log('coroutine4-2:' + z + x); // z=undefined, x=abc
}

I would introduce another function prototype: waitFor

waitFor = function(check, ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?waitFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    var thread = setInterval(function() {
        if(check()) {
            clearInterval(thread);
            new Function(funcArgs, funcBody).apply(context, args);
        }
    }, ms?ms:100);
    return this;
}

It waits for "check" function until it returns true. It checks the value every 100 ms. You can adjust it by passing additional argument. Consider the testing coroutine2:

function coroutine2(c) {
    /* Some code here */
    this.a = 1;
    console.log('coroutine2-1:' + this.a++);
    return sleepFor(500).yield;

    /* Next */
    console.log('coroutine2-2:' + this.a++);
    console.log('coroutine2-2:waitFor c.a>100:' + c.a);
    return waitFor(function() {
        return c.a>100;
    }).yield;

    /* The rest of the code */
    console.log('coroutine2-3:' + this.a++);
}

Also in the pretty style we love so far. Actually I hate the nested callback. It is easily understood that the coroutine2 will wait for the completion of coroutine1. Interesting? Ok, then run the following code:

this.a = 10;
console.log('outer-1:' + this.a++);
var c1 = new coroutine1();
var c2 = new coroutine2(c1);
console.log('outer-2:' + this.a++);

The output is:

outer-1:10
coroutine1-1:start
coroutine2-1:1
outer-2:11
coroutine2-2:2
coroutine2-2:waitFor c.a>100:100
coroutine1-2:complete
coroutine2-3:3

Outer is immediately completed after initialised coroutine1 and coroutine2. Then, coroutine1 will wait for 3000 ms. Coroutine2 will enter into step 2 after waited for 500 ms. After that, it will continue step 3 once it detects the coroutine1.a values > 100.

Beware of that there are three contexts to hold variable "a". One is outer, which values are 10 and 11. Another one is in coroutine1, which values are 100 and 101. The last one is in coroutine2, which values are 1,2 and 3. In coroutine2, it also waits for c.a which comes from coroutine1, until its value is greater than 100. 3 contexts are independent.

The whole code for copy&paste:

sleepFor = function(ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?sleepFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    setTimeout(function() {
        new Function(funcArgs, funcBody).apply(context, args);
    }, ms);
    return this;
}

waitFor = function(check, ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?waitFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    var thread = setInterval(function() {
        if(check()) {
            clearInterval(thread);
            new Function(funcArgs, funcBody).apply(context, args);
        }
    }, ms?ms:100);
    return this;
}

function coroutine1() {
    this.a = 100;
    console.log('coroutine1-1:start');
    return sleepFor(3000).yield;
    console.log('coroutine1-2:complete');
    this.a++;
}

function coroutine2(c) {
    /* Some code here */
    this.a = 1;
    console.log('coroutine2-1:' + this.a++);
    return sleepFor(500).yield;

    /* next */
    console.log('coroutine2-2:' + this.a++);
    console.log('coroutine2-2:waitFor c.a>100:' + c.a);
    return waitFor(function() {
        return c.a>100;
    }).yield;

    /* The rest of the code */
    console.log('coroutine2-3:' + this.a++);
}

this.a = 10;
console.log('outer-1:' + this.a++);
var c1 = new coroutine1();
var c2 = new coroutine2(c1);
console.log('outer-2:' + this.a++);

It is tested in Internet Explorer 11 and Chrome 49. Because it uses arguments.callee, so it may be trouble if it runs in strict mode.

Pentosan answered 4/6, 2009 at 14:41 Comment(0)
P
0

I'm sure there is a million ways to do this one better, but I thought I would give it a try by creating an object:

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

And use it like:

// // // 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 // // //
Piotrowski answered 4/6, 2009 at 14:41 Comment(0)
F
0

The short answer is no, not in JavaScript by itself. Your solution seems to be the only way to not return control back to the environment.

This is necessary if the environment does not support events. They probably wouldn't support the setTimeout either.

setTimeout is definitely the best way if you are in an event driven environment such as a browser or Node.js.

Feed answered 4/6, 2009 at 14:41 Comment(0)
S
0

A good alternative in some situations is to display a top-level message panel to stop user interaction, and then hide it again when you get the result you're waiting for (asynchronously). That allows the browser to get on with background tasks, but pauses the workflow until you've got your result back.

Spartan answered 4/6, 2009 at 14:41 Comment(0)
S
-1

Short answer

Use delay npm library. Typescript is supported

Example

const delay = require('delay');

(async () => {
    bar();

    await delay(100);

    // Executed 100 milliseconds later
    baz();
})();

Source: https://www.npmjs.com/package/delay

Long answer

I like the answer of Dan Dascalescu but I have been wondering is not there any library which provide that function? There it is - delay npm library. It even supports typescript

Stewardess answered 4/6, 2009 at 14:41 Comment(0)
M
-1

I use the multithread HTML5 Worker which will be able to abort an synchronous XMLHttpRequest pointing to an unresponsive URL. This does not block the browser.

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

Morceau answered 4/6, 2009 at 14:41 Comment(0)
W
-2
require('deasync').sleep(100);
Wince answered 4/6, 2009 at 14:41 Comment(2)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Usk
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. You can find more information on how to write good answers in the help center: stackoverflow.com/help/how-to-answer . Good luck 🙂Handball
S
-2

The problem with using an actual sleep function is that JavaScript is single-threaded and a sleep function will pretty much make your browser tab hang for that duration.

Scissile answered 4/6, 2009 at 14:41 Comment(1)
That was already said in a previous answer.Feed
G
-2

A very simple way to do do sleep, that will be compatible with anything that runs JavaScript... This code has been tested with something like 500 entries, and CPU and memory usage is still not visible on my web browsers.

Here is one function that waits until the node becomes visible...

This function creates a new context function () {} to avoid recursion. We placed code that does the same as the caller code inside this new context. We use the function Timeout to call our function after a few time second.

var get_hyper = function(node, maxcount, only_relation) {
    if (node.offsetParent === null) {
        // node is hidden
        setTimeout(function () { get_hyper(node, maxcount, only_relation)}, 
                   1000);
        return;
    };

    // Enter the code here that waits for that node becoming visible
    // before getting executed.

};
Gauger answered 4/6, 2009 at 14:41 Comment(0)
F
-2

I had a similar problem, having to wait for control existence and checking in intervals. Since there is no real sleep, wait or pause in JavaScript and using await / async is not supported properly in Internet Explorer, I made a solution using setTimeOut and injecting the function in case of successfully finding the element. Here is the complete sample code, so everyone can reproduce and use it for their own project:

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
        var ElementSearchStatus = {
            None: 0,
            Found: 1,
            NotFound: 2,
            Timeout: 3
        };

        var maxTimeout = 5;
        var timeoutMiliseconds = 1000;

        function waitForElement(elementId, count, timeout, onSuccessFunction) {
            ++count;
            var elementSearchStatus = existsElement(elementId, count, timeout);
            if (elementSearchStatus == ElementSearchStatus.None) {
                window.setTimeout(waitForElement, timeoutMiliseconds, elementId, count, timeout, onSuccessFunction);
            }
            else {
                if (elementSearchStatus == ElementSearchStatus.Found) {
                    onSuccessFunction();
                }
            }
        }

        function existsElement(elementId, count, timeout) {
            var foundElements = $("#" + elementId);
            if (foundElements.length > 0 || count > timeout) {
                if (foundElements.length > 0) {
                    console.log(elementId + " found");
                    return ElementSearchStatus.Found;
                }
                else {
                    console.log("Search for " + elementId + " timed out after " + count + " tries.");
                    return ElementSearchStatus.Timeout;
                }
            }
            else {
                console.log("waiting for " + elementId + " after " + count + " of " + timeout);
                return ElementSearchStatus.None;
            }
        }

        function main() {
            waitForElement("StartButton", 0, maxTimeout, function () {
                console.log("found StartButton!");
                DoOtherStuff("StartButton2")
            });
        }

        function DoOtherStuff(elementId) {
            waitForElement(elementId, 0, maxTimeout, function () {
                console.log("found " + elementId);
                DoOtherStuff("StartButton3");
            });
        }
    </script>
</head>
<body>
    <button type="button" id="StartButton" onclick="main();">Start Test</button>
    <button type="button" id="StartButton2" onclick="alert('Hey ya Start Button 2');">Show alert</button>
</body>
</html>
Floyd answered 4/6, 2009 at 14:41 Comment(0)
L
-2

JavaScript functions doesn't allow any suspension. With synchronous JavaScript, procedures are implemented. Procedures await I/O operations and sleep timeouts. It is available for JavaScript 1.7.

Demos:

Leinster answered 4/6, 2009 at 14:41 Comment(0)
A
-2

Use three functions:

  1. A function which calls setInterval to start the loop
  2. A function which calls clearInterval to stop the loop, then calls setTimeout to sleep, and finally calls to within the setTimeout as the callback to restart the loop
  3. A loop which tracks the number of iterations, sets a sleep number and a maximum number, calls the sleep function once the sleep number has been reached, and calls clearInterval after the maximum number has been reached

var foo = {};

function main()
{
  'use strict';

  /* Initialize global state */
  foo.bar = foo.bar || 0;

  /* Initialize timer */
  foo.bop = setInterval(foo.baz, 1000);
}

sleep =
  function(timer)
  {
    'use strict';
    clearInterval(timer);
    timer = setTimeout(function(){main()}, 5000);
  };

foo.baz =
  function()
  {
    'use strict';

    /* Update state */
    foo.bar = Number(foo.bar + 1) || 0;

    /* Log state */
    console.log(foo.bar);

    /* Check state and stop at 10 */
    (foo.bar === 5) && sleep(foo.bop);
    (foo.bar === 10) && clearInterval(foo.bop);
  };

main();

Event Loop

References

Aquifer answered 4/6, 2009 at 14:41 Comment(0)
S
-2

Another possible way is:

var _timer;
clearTimeout(_timer);
_timer = setTimeout(function() {
    // Your code
}, 1000); // Delay for 1 s.
Sena answered 4/6, 2009 at 14:41 Comment(1)
An explanation would be in order. E.g., how is it different from previous answers?Feed
K
-2

Here is a way to sleep in a .hta script, such that when the script wakes up it executes the next command in sequence, as is necessary in a loop. This is a real sleep; it does not keep a processor busy during the sleep. For example, the processor is able to download and render pages during the sleep.

Just once, near the beginning of the code, go

var WSHShell = new ActiveXObject ("WScript.Shell");

For a sleep of e.g. 1 second = 1000 milliseconds, execute the statement

WSHShell.Run('Sleep.js 1000', 3, true);

In the same directory as the script is the file Sleep.js, which contains the following one line:

WScript.Sleep(WScript.Arguments (0));

(Beware; 0 is in parentheses, not brackets.) The latter is the line that actually performs the sleep. The argument true in the preceding snippet makes the call synchronous. The 3 in the preceding argument seems not to have any effect, but you need some argument so that true is the third argument.

Microsoft says "The WScript object ... never needs to be instantiated before invoking its properties and methods, and it is always available from any script file.", but that's not true. It is available in a free-standing .js file such as the above, but apparently not in a .js file used by a .hta file, so that is why it must be in a separate file, invoked as above.

Kiethkiev answered 4/6, 2009 at 14:41 Comment(1)
But it is Windows/Internet Explorer-specific(?). It uses COM (disguised as ActiveX). "WSH" is Windows Script Host.Feed
A
-3

I got Promise is not a constructor using the top answer. If you import bluebird you can do this. It is the simplest solution, in my opinion.

import * as Promise from 'bluebird';

await Promise.delay(5000)
Avalos answered 4/6, 2009 at 14:41 Comment(0)
O
-3

It is now also possible to use the native module util to promisify regular sync functions.

const { promisify } = require('util')
const sleep = promisify(setTimeout)

module.exports = () => {
  await someAsyncFunction()
  await sleep(2000)
  console.log('2 seconds later...')
}
Oidea answered 4/6, 2009 at 14:41 Comment(1)
you cannot use await inside a non-async function (in your example, the exported function)Nace
I
-4

In LiveScript (which compiles to JavaScript), you can do like the following:

sleep = (ms, func) -> set-timeout func, ms

console.log "hello-1"
<- sleep 2000ms
console.log "hello-2"
<- sleep 2000ms
console.log "hello-3"
Irrecusable answered 4/6, 2009 at 14:41 Comment(2)
that is just wrapping setTimeout in a function called sleep :pFarber
No it doesn't. I am very much against languages that just mangle JS sintax without any added value (i.e.: coffescript)Farber
D
-7

This might work. It worked for me in C and JavaScript.

function sleep(time) {
  var x = 0;
  for(x = 0;x < time;x++) {/* Do nothing */}
}
Dixie answered 4/6, 2009 at 14:41 Comment(2)
The use of a for/while/foreach should be avoid in javascript. Consider setTimeout() or setInverval() insteadRhatany
This will block for an arbitrary amount of time, according to how fast the user's processor can count. I don't imagine many people will find this helpful.Christly
S
-8

Each and every solution I've read so far would be like "let's get to sleep and look what happened, tomorrow".

setInterval(callback, time) would wait time long and then call the callback, while blocking the runtime. The current implementation of "setInterval" is far from being thread-save, not even to mind concurrency.

While the sparse solutions mentioned look like, guess what, C# (laughs), they still don't work like in C#/.NET. They still work like in C.

JavaScript currently does not provide an architecture to accomplish real multi-threading. The best approach would be TypeScript, but still this lacks so much of a real solution that it... hurts. JavaScript, and jQuery, and AJAX, and jNode, and even TypeScript are just a bunch of wannabes relying on the goods and bads of the moods of the implementers. Fact. Full stop.

Summersault answered 4/6, 2009 at 14:41 Comment(1)
setInterval does not block - and more importantly, it repeats every time. This isn't even close to what is being asked.Christly
W
-11

Or just create this:

function yourFunction(){

   // Do something
   setInterval(myFunc(), 1000);
   // Do something else
}

function myFunc(){
   return;
}

This will just wait the interval specified and call the function which will just do nothing.

Worldly answered 4/6, 2009 at 14:41 Comment(4)
setInterval will call the function frequently after the timer is completedExemplum
setInterval() will create a fork and keep calling the function every 1000ms. But it will not pause the execution. This means // do something else will continue immediately.Toon
and I think you wanted to say: setInterval(myFunc, 1000).Toon
Three issues I see here: 1. You probably meant setTimeout(myFunc, 1000). 2. The first argument must be the function itself [myFunc], not the result of the function [given by myFunc()]. 3. The OP explicitly wanted a real sleep in a middle of a function, not a delay for a piece of code.Doublebank

© 2022 - 2024 — McMap. All rights reserved.