Sleep in JavaScript - delay between actions - javascript

Is there a way I can do a sleep in JavaScript before it carries out another action?
Example:
var a = 1 + 3;
// Sleep 3 seconds before the next action here.
var b = a + 4;

You can use setTimeout to achieve a similar effect:
var a = 1 + 3;
var b;
setTimeout(function() {
b = a + 4;
}, (3 * 1000));
This doesn't really 'sleep' JavaScript—it just executes the function passed to setTimeout after a certain duration (specified in milliseconds). Although it is possible to write a sleep function for JavaScript, it's best to use setTimeout if possible as it doesn't freeze everything during the sleep period.

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 debuggin - 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.

ECMAScript 6 version, using generators with yield for "code blocking":
Because the original question was posted seven years ago, I didn't bother answering with the exact code, because it's just way too easy and already answered. This should help in more complicated problems, like if you need at least two sleeps, or if you are planning to sequence asynchronous execution. Feel free to modify it to fit your needs.
let sleeptime = 100
function* clock()
{
let i = 0
while( i <= 10000 )
{
i++
console.log(i); // actually, just do stuff you wanna do.
setTimeout(
()=>
{
clk.next()
}
, sleeptime
)
yield
}
}
let clk = clock()
clk.next()
function*
() => arrow function
You can also chain events via Promises:
function sleep(ms)
{
return(
new Promise(function(resolve, reject)
{
setTimeout(function() { resolve(); }, ms);
})
);
}
sleep(1000).then(function()
{
console.log('1')
sleep(1000).then(function()
{
console.log('2')
})
})
Or much simpler and a less fancy way would be
function sleep(ms, f)
{
return(
setTimeout(f, ms)
)
}
sleep(500, function()
{
console.log('1')
sleep(500, function()
{
console.log('2')
})
})
console.log('Event chain launched')
If you're just waiting for some condition to happen you can wait like this
function waitTill(condition, thenDo)
{
if (eval(condition))
{
thenDo()
return
}
setTimeout(
() =>
{
waitTill(condition, thenDo)
}
,
1
)
}
x=0
waitTill(
'x>2 || x==1'
,
() =>
{
console.log("Conditions met!")
}
)
// Simulating the change
setTimeout(
() =>
{
x = 1
}
,
1000
)

2018 Update
The latest Safari, Firefox and Node.js are now also supporting async/await/promises.
Using async/await/Promises:
(As of 1/2017, supported on Chrome, but not on Safari, Internet Explorer, Firefox, Node.js)
'use strict';
function sleep(ms) {
return new Promise(res => setTimeout(res, ms));
}
let myAsyncFunc = async function() {
console.log('Sleeping');
await sleep(3000);
console.log('Done');
}
myAsyncFunc();
2017 Update
JavaScript has evolved since this question was asked and now has generator functions, and the new async/await/Promise is being rolled out. Below there are two solutions, one with generator function that will work on all modern browsers, and another, using the new async/await that is not yet supported everywhere.
Using a generator function:
'use strict';
let myAsync = (g) => (...args) => {
let f, res = () => f.next(),
sleep = (ms) => setTimeout(res, ms);
f = g.apply({sleep}, args); f.next();
};
let myAsyncFunc = myAsync(function*() {
let {sleep} = this;
console.log("Sleeping");
yield sleep(3000);
console.log("Done");
});
myAsyncFunc();
Pay attention to the fact that both these solutions are asynchronous in nature. This means that the myAsyncFunc (in both cases) will return while sleeping.
It is important to note that this question is different than What is the JavaScript version of sleep()? where the requestor is asking for real sleep (no other code execution on the process) rather than a delay between actions.

Here's a very simple way to do it that 'feels' like a synchronous sleep/pause, but is legit js async code.
// Create a simple pause function
const pause = (timeoutMsec) => new Promise(resolve => setTimeout(resolve,timeoutMsec))
async function main () {
console.log('starting');
// Call with await to pause. Note that the main function is declared asyc
await pause(3*1000)
console.log('done');
}

Another way to do it is by using Promise and setTimeout (note that you need to be inside a function and set it as asynchronous with the async keyword) :
async yourAsynchronousFunction () {
var a = 1+3;
await new Promise( (resolve) => {
setTimeout( () => { resolve(); }, 3000);
}
var b = a + 4;
}

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, ...")

You can use plain javascript, this will call your function/method after 5 seconds:
setTimeout(()=> { your_function(); }, 5000);

Here's a re-write and a demo of a Promise-based sleep() using call to setTimeout(). It also demos a regular call to setTimeout().
function sleep(ms) {
return new Promise(resolve => setTimeout(() => resolve(), ms))
}
console.log("Synchronous call");
sleep(2000)
.then(() => console.log("Asynchronous call"));
Image of its run on Repl.it
function sleep(ms) {
return new Promise(resolve => setTimeout(() => resolve(), ms))
}
console.log("Synchronous call 1");
sleep(4000)
.then(() => console.log("Asynchronous call 1"));
sleep(2000)
.then(() => console.log("Asynchronous call 2"));
console.log("Synchronous call 2");
sleep(3000)
.then(() => console.log("Asynchronous call 3"));
console.log("Synchronous call 3");
sleep(5000)
.then(() => console.log("Asynchronous call 4"))
.then(
sleep(7000)
.then(()=>console.log("Asynchronous call 5"))
)
console.log("Synchronous call 4");
setTimeout(() => {console.log("Asynchronous call 6")}, 8000);
console.log("Synchronous call 5");

function delayer(ms){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve();
}, ms)
})
}
async function myFunction(){ // Function Must be async.
console.log("First Console")
await delayer(2000); // This Will Stop The Code For 2 Seconds
console.log("Second Console")
}
myFunction()

For what is worth
isPause = true;
setTimeout(()=>{isPause=false},2000);
while (!isPause) {
// delay for 2 seconds
}

You can use setTimeout to call a callback after a specified amount of time:
setTimeout(() => {
console.log('Called after 1 second');
}, 1000);
If you want to use setTimeout as a promise, you can do this:
const delay = milliseconds => new Promise(resolve => { setTimeout(resolve, milliseconds); });
await delay(1000);
console.log('Called after 1 second');
Since Node.js 16, this functionality is also built-in:
import {setTimeout as delay} from 'node:timers/promises';
await delay(1000);
console.log('Called after 1 second');
If you want a synchronous delay in Node.js or in the browser outside of the main thread, you can use Atomics.wait:
const delay = milliseconds => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
await delay(1000);
console.log('Called after 1 second');

There are several ways to solve this problem. If we use the setTimeout function, let's get to know it first.
This function has three parameters: function or code, delay (in milliseconds) and the parameters.
Since the function or code parameter is required, the others are optional.
Once you have not entered the delay, it will be set to zero.
For more details about the setTimeout() go to this link.
Simplified version:
var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(function(){
b = a + 4;
console.log('b = ' + b);
}, 1000);
output:
a = 4
24 --> Number identifier of the list of active timeouts
b = 8
Using the parameter pass:
var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(myFunction, 1000, a);
function myFunction(a)
{
var b = a + 4;
console.log('b = ' + b);
}
output:
a = 4
25 --> Number identifier of the list of active timeouts
b = 8
Browser Support:
Chrome Firefox Edge Safari Opera
1.0 1.0 4.0 1.0 4.0

This is my model that shows how to "sleep" or "DoEvents" in javascript using a generator function (ES6). Commented code:
<html>
<head>
<script>
"use strict"; // always
// Based on post by www-0av-Com https://stackoverflow.com/questions/3143928
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
var divelt, time0, globaln = 0; // global variables
var MainGenObj = Main(); // generator object = generator function()
window.onload = function() {
divelt = document.getElementsByTagName("body")[0]; // for addline()
addline("typeof Main: " + typeof Main);
addline("typeof MainDriver: " + typeof MainDriver);
addline("typeof MainGenObj: " + typeof MainGenObj);
time0 = new Date().valueOf(); // starting time ms
MainDriver(); // do all parts of Main()
}
function* Main() { // this is "Main" -- generator function -- code goes here
// could be loops, or inline, like this:
addline("Part A, time: " + time() + ", " + ++globaln); // part A
yield 2000; // yield for 2000 ms (like sleep)
addline("Part B, time: " + time() + ", " + ++globaln); // part B
yield 3000; // yield for 3000 ms (or like DoEvents)
addline("Part Z, time: " + time() + ", " + ++globaln); // part Z (last part)
addline("End, time: " + time());
}
function MainDriver() { // this does all parts, with delays
var obj = MainGenObj.next(); // executes the next (or first) part of Main()
if (obj.done == false) { // if "yield"ed, this will be false
setTimeout(MainDriver, obj.value); // repeat after delay
}
}
function time() { // seconds from time0 to 3 decimal places
var ret = ((new Date().valueOf() - time0)/1000).toString();
if (ret.indexOf(".") == -1) ret += ".000";
while (ret.indexOf(".") >= ret.length-3) ret += "0";
return ret;
}
function addline(what) { // output
divelt.innerHTML += "<br />\n" + what;
}
</script>
</head>
<body>
<button onclick="alert('I\'m alive!');"> Hit me to see if I'm alive </button>
</body>
</html>

I know this question is old, but if someone is searching for this,
there's a cleaner way of ACTUALLY sleeping in javascript using promises
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const run = async () => {
while(true){
console.log("yay1")
await sleep(3000)
console.log("next action")
}
}
run()
This will always have a 3 seconds pause between the first log and second log
What happens here is,
Using await the code execution of JavaScript pauses until the
promise is resolved.
The promise will be resolved when the resolver gets fired. The
resolver will be fired when setTimeout is executed.
setTimeout will be executed after a given duration in milliseconds.

Related

How to wait for the recursive loop to finish and display the message?

I'm running a recursive function with setTimeout, what I've noticed is that javascript goes straight through the wait() function and doesn't wait for it to finish. It goes right through and leaves the wait() method working by itself.
wait(100, 30)
function wait(time, limit) {
console.log('value >> ' + limit)
if (limit < 0) return 'success'
setTimeout(function () {
wait(time, --limit)
}, time)
}
console.log('hi')
Note that my "hi' message is at the top when running the script, because it went straight through without waiting for the recursive loop. My "hi" message should be at the end.
Can anyone help me leave the hi message at the end after running all the loop?
You could handover a function which is called at the end of waiting.
function wait(time, limit, fn) {
console.log('value >> ' + limit)
if (limit < 0) return fn();
setTimeout(function () {
wait(time, --limit, fn);
}, time)
}
function sayHi() { console.log('hi'); }
wait(100, 30, sayHi);
you can also simply return the message which do you want:
wait(100, 30);
function wait(time, limit) {
console.log("value >> " + limit);
if (limit < 0) return console.log("hi");
setTimeout(function () {
wait(time, --limit);
}, time);
}
In addition to Nina's approach and also for use cases where a callback can not be implemented as easily as demonstrated with Nina's example code, one might use an abstraction for it, which for JavaScript is Promises.
Here, instead of 30 times delaying for 100 milliseconds until logging, one would implement wait as promise which resolves after 3 seconds with the additional logging provided as thenable ...
const wait = new Promise(resolve => setTimeout(resolve, 3000));
wait.then(() => console.log('hi'));
console.log({ wait: String(wait) });
.as-console-wrapper { min-height: 100%!important; top: 0; }

Calling a function as many times as possible in a given time interval

I am trying to call the function test() as many times as possible in a given time interval.
Here the function should be running for 15 seconds.
function test(): void; // Only type def
function run() {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 15000); // 15 seconds
while (true) {
test();
}
});
}
run()
.then(() => {
console.log('Ended');
});
However, the function doesn't stop running, and the Ended console.log does not appear. (Promise not resolved obviously). Is there a way to achieve this in Javascript ?
I was wondering, I could probably use console timers and put the condition in the while statement ? (But is that the best way ?)
The reason why your function does not stop executing is because resolving a promise does not stop script executing. What you want is to store a flag somewhere in your run() method, so that you can flip the flag once the promise is intended to be resolved.
See proof-of-concept below: I've shortened the period to 1.5s and added a dummy test() method just for illustration purpose:
let i = 0;
function test() {
console.log(`test: ${i++}`);
}
function run() {
return new Promise(resolve => {
let shouldInvoke = true;
setTimeout(() => {
shouldInvoke = false;
resolve();
}, 1500); // 15 seconds
const timer = setInterval(() => {
if (shouldInvoke)
test();
else
window.clearInterval(timer);
}, 0);
});
}
run()
.then(() => {
console.log('Ended');
});

Replacing recursive function with simpler loop

I'm new to the concept of recursion. I've been practicing JavaScript with some codes from javascript30.com. I've stumbled upon the below mention function:
function peep() {
const time = randomTime(200, 1000);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
if (!timeUp) peep();
}, time);
}
Link to full code: https://codepen.io/luckyseven444/pen/bXqXbP (code is running ok in my PC)
Is it possible to form a simple loop rather than the recursive function peep() mentioned above? I mean I want to replace the second peep() inside setTimeout function.
Thanks
If you really insist, you can create an async function, wrap setTimeout with a Promise, await the Promise and add a loop:
async function test() {
for (let i = 0; i < 10; i++) {
console.log('before setTimeout', i);
await new Promise(resolve => setTimeout(() => {
console.log('timeout elapsed', i);
resolve();
}, 1000));
}
}
test();

ES6 promises with timeout interval

I'm trying to convert some of my code to promises, but I can't figure out how to chain a new promise inside a promise.
My promise function should check the content of an array every second or so, and if there is any item inside it should resolve. Otherwise it should wait 1s and check again and so on.
function get(){
return new Promise((resolve) => {
if(c.length > 0){
resolve(c.shift());
}else{
setTimeout(get.bind(this), 1000);
}
});
}
let c = [];
setTimeout(function(){
c.push('test');
}, 2000);
This is how I expect my get() promise function to work, it should print "test" after 2 or 3 seconds max:
get().then((value) => {
console.log(value);
});
Obviously it doesn't work, nothing is ever printed
setTimeout has terrible chaining and error-handling characteristics on its own, so always wrap it:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
function get(c) {
if (c.length) {
return Promise.resolve(c.shift());
}
return wait(1000).then(() => get(c)); // try again
}
let c = [];
get(c).then(val => console.log(val));
wait(2000).then(() => c.push('test'));
While you didn't ask, for the benefit of others, this is a great case where async/await shines:
const wait = ms => new Promise(r => setTimeout(r, ms));
async function get(c) {
while (!c.length) {
await wait(1000);
}
return c.shift();
}
let c = [];
get(c).then(val => console.log(val));
wait(2000).then(() => c.push('test'));
Note how we didn't need Promise.resolve() this time, since async functions do this implicitly.
The problem is that your recursive call doesn't pass the resolve function along, so the else branch can never call resolve.
One way to fix this would be to create a closure inside the promise's callback so that the recursive call will have access to the same resolve variable as the initial call to get.
function get() {
return new Promise((resolve) => {
function loop() {
if (c.length > 0) {
resolve(c.shift());
} else {
setTimeout(loop, 1000);
}
}
loop();
});
}
let c = [];
setTimeout(function() {
c.push('test');
}, 2000);
get().then(val => console.log(val));
In the else case, you never resolve that promise. get might create another one, but it is returned to nowhere.
You should promisify your asynchronous function (setTimeout) on the lowest level, and then only chain your promises. By returning the result of the recursive call from a then callback, the resulting promise will resolve with the same result:
function delayAsync(time) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
function get(c) {
if (c.length > 0){
return Promise.resolve(c.shift());
} else {
return delay(1000).then(() => {
return get(c); // try again
});
}
}
What you need is a polling service, which checks periodically for specific condition prior proceeding with promise resolution. Currently when you run setTimeout(get.bind(this), 1000); you are creating a new instance of the promise without actually resolving the initial promise, because you don't reference to the initial resolve function that you created.
Solution:
Create a new callback function that you can reference to it inside the promise
Pass the resolve & reject as params in the setTimeout invocation e.g. setTimeout(HandlePromise, 1000, resolve, reject, param3, param4 ..); setTimeout API
function get() {
var handlerFunction = resolve => {
if (c.length > 0) {
resolve(c.shift());
} else {
setTimeout(handlerFunction, 1000, resolve);
}
};
return new Promise(handlerFunction);
}
let c = [];
setTimeout(function() {
c.push("test");
}, 2000);
get().then(value => {
console.log(value);
});
For more information look into javascript polling article
You could try this solution. Since JS needs to free itself to download the images, I use await within an asynchronous function and an asynchronous call to wake up JS after a delay
private async onBeforeDoingSomething() : void {
await this.delay(1000);
console.log("All images are loaded");
}
private delay (ms : number = 500) : Promise<number> {
return new Promise((resolve,reject) => {
const t = setTimeout( () => this.areImgsLoaded(resolve), ms);
});
}
private async areImgsLoaded (resolve) {
let reload = false;
const img = document.querySelectorAll('img');
console.log("total of images: ",img.length);
for (let i = 0; i < img.length; i++){
if (!img[i]["complete"]) {
console.log("img not load yet");
reload = true;
break;
}
}
if (reload) {
await this.delay();
}
resolve();
}
Use setInterval to check every second. Run this script to understand.
let c = [];
function get(){
return new Promise((resolve) => {
var i = setInterval(function(){
if(c.length > 0){
resolve(c.shift());
clearInterval(i);
}
}, 1000);
});
}
setTimeout(function(){
c.push('test');
}, 2000);
get().then((value) => {
console.log(value);
});

Passing rest of the codes as callback function

In a middle of already completed javascript function, you want to call a new async function. So you need to pass, "rest of the code" as a callback function as parameter to this new function.
function sample() {
alert("a bunch of codes");
alert("another a bunch of codes");
}
I have to change the function as below.
function sample() {
alert("a bunch of codes");
var cb = function () {
alert("another a bunch of codes");
};
newFunction(cb);
}
What if I want to add another function that has to wait first one ? Then I got numerous multiple levels of callback functions to the wait another..
So what is the best practice on ES5 ?
In ES5, just like you said you have to nest multiple callbacks inside each other.
Example:
function myFunction2(){
console.log(2);
let myFunction = () => {
console.log(1);
}
myFunction();
}
myFunction2();
// OUTPUT
// 2
// 1
ES6 also provides a new alternative, promises.
Example:
let myPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve(1);
}, 250);
});
console.log(2);
myPromise.then((successMessage) => {
console.log(successMessage);
});
// OUTPUT
// 2
// 1
ES8 has provides an even better alternative(although it is just syntactic sugar based on promises) but you can use async functions with await.
Example:
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function add1(x) {
const a = await resolveAfter2Seconds(20);
const b = await resolveAfter2Seconds(30);
return x + a + b;
}
add1(10).then(v => {
console.log(v); // prints 60 after 4 seconds.
});
Keep in mind though, that you probably need to use Babel to transpile your js in order to be compatible with all browsers.

Categories

Resources