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.
Solution 1
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));
Or
const sleep = ms => 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,
awaitcan only be executed in functions prefixed with theasynckeyword, or at the top level of your script in an increasing number of environments.awaitonly pauses the currentasyncfunction. 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 usingAtomics.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:
- Promises, a native feature of ES2015 (aka ES6). We also use arrow functions in the definition of the sleep function.
- The
async/awaitfeature lets the code explicitly wait for a promise to settle (resolve or reject).
Compatibility
- promises are supported in Node v0.12+ and widely supported in browsers, except IE
async/awaitlanded in V8 and has been enabled by default since Chrome 55 (released in Dec 2016)- it landed in Node 7 in October 2016
- and also landed in Firefox Nightly in November 2016
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.
Solution 2
(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.
Solution 3
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!
});
Solution 4
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
Solution 5
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.
Solution 6
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.
Solution 7
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.
*/
}
Solution 8
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');
Solution 9
Use:
await new Promise(resolve => setTimeout(resolve, 2000));
Make sure your calling function is async. This is verified and is working fine.
Solution 10
I've searched for a sleep solution too (not for production code, only for development and tests) and found this article:
...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. :)
Solution 11
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) {}
}
Solution 12
Since April 2021 (Node.js 16+), a new promisified version of setTimeout() is available:
import { setTimeout } from 'timers/promises'
const res = await setTimeout(2000, 'result')
console.log(res); // Prints 'result'
Thank @kigiri. See the official documentation: https://nodejs.org/api/timers.html#timerspromisessettimeoutdelay-value-options
Solution 13
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.
Solution 14
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.
Solution 15
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
Solution 16
I personally like the simple:
function sleep(seconds){
var waitUntil = new Date().getTime() + seconds*1000;
while(new Date().getTime() < waitUntil)
true;
}
then:
sleep(2); // Sleeps for 2 seconds
I'm using it all the time to create fake load times while creating scripts in p5.js.
Solution 17
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){}
%>
Solution 18
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.
Solution 19
The shortest solution without any dependencies:
await new Promise(resolve => setTimeout(resolve, 5000));
Solution 20
One-liner using Promises
const sleep = t => new Promise(s => setTimeout(s, t));
Demo
const sleep = t => new Promise(s => setTimeout(s, t));
// Usage
async function demo() {
// Count down
let i = 6;
while (i--) {
await sleep(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 sleep(1000);
const result = a + b;
console.log(`${a} + ${b} = ${result}`);
return result;
}, Promise.resolve(0));
console.log("sum", sum);
}
demo();
Solution 21
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');
Solution 22
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.
Solution 23
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.
Solution 24
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);
}
}
Solution 25
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>
Solution 26
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.
Solution 27
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
Solution 28
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, ...")
Solution 29
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.
Solution 30
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.
