Here is my problem:
My main function:
const mainFunction = () => {
const reports = JSON.parse($sessionStorage.datas);
// reports contains array of objects.
// consider i have two objects inside one array, so the loop will execute two times now
reports.forEach((item) => {
this.openReport(item);
});
};
mainFunction();
openReport function:
this.openReport = (report) => {
console.log('openReport working');
// some async functions will be here
// ajax calls
this.openTab(report);
};
openTab function:
this.openTab = (report) => {
console.log('handleOpenTab function working');
}
Output:
// Now i have two objects, so forEach works two times.
'openReport working'
'openReport working'
'handleOpenTab function working'
'handleOpenTab function working'
My expected output :
'openReport working'
'handleOpenTab function working'
'openReport working'
'handleOpenTab function working'
How to achieve this? i am unable to use async await inside my forEach function, because using old node version.
If its possible to use async/await for this problem, i will try to upgrade my node version.
Using promises, it would look something like this probably:
this.openReport = (report) => {
console.log('openReport working');
// some async functions will be here
// ajax calls
return new Promise(function(resolve, reject) {
ajaxCall('url', resolve); // reject as necessary!
}).then(answer => {
this.openTab(report);
return answer;
});
};
const mainFunction = () => {
const reports = JSON.parse($sessionStorage.datas);
// reports contains array of objects.
function getNextReport(index) {
if (index >= reports.length) return Promise.resolve();
let item = reports[index];
return this.openReport(item).then(function(answer) {
// do something with answer
return getNextReport(index+1);
});
}
return getNextReport(0);
};
This is a simple version of what I'm trying to do in my application. I have an if statement which evaluates the result of a function call and then populates an array if the statement comes back as true. AFTER the if statement is completely finished, I want to run some more code such as the console.log as seen below.
I understand that the if's evaluation is taking too long to finish and javascript just continues to the console.log because of its asynchronicity. How do I make the code wait for the if statement to complete?
var tabs = [];
if (isTrue()) {
tabs.push('some string');
}
console.log(tabs[1]);
function isTrue() {
setTimeout(function() {
return true;
}, 500)
}
You can just wrap your code in a Promise and consume the returned values by calling then on it:
var tabs = [];
isTrue().then(res => {
if (res) {
tabs.push('some string');
}
return tabs;
}).then(arr => {
console.log(arr);
});
function isTrue() {
//Just wrap your existing code in a Promise constructor
return new Promise((resolve, reject) => {
setTimeout(() => {
//Pass whatever value you want to consume later to resolve
resolve(true);
}, 500)
});
}
You could pass a callback to the isTrue() function, something like:
function isTrue(_callback) {
setTimeout(function() {
// code here
// Call the callback when done
if (typeof(_callback) === 'function')
_callback(tabs);
});
}
function showTabs(tabs) {
console.log(tabs[1]);
}
isTrue(showTabs);
Ought to work.
Using modern javascript, you can achieve that using promises and async/await:
const isTrue = () => new Promise(resolve => setTimeout(resolve, 500, true));
// you can only use `await` inside an `async` function
async function main() {
// better use `let` instead of `var` since `let` is block scoped,
// see:
// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let>
let tabs = [];
if (await isTrue()) {
tabs.push('some string');
}
// array's index start by 0, not 1
console.log(tabs[0]);
}
main();
(this code also use arrow functions for isTrue.)
isTrue() returns undefined. The return true inside of the setTimeout callback will return back to the timeout call, not to the isTrue() call. The code executes immeadiately and there is no asynchronity involved (except for that timer that does nothing).
I need to somehow loop over the work array passed to _start then
for each of the items in the array, I need to somehow call the corresponding function with the same name.
I don't have control over the number of items in work the array or the number of items, I do know that there will always be a corresponding function.
I don't want to call all the functions at the same time, once the first function resolves after 3 seconds, I then want to call the second function, once the second function resolves after 3 seconds I then want to call the third function. Once the third function resolves after another 3 seconds I want to call _done().
In this example each function takes 3 seconds to complete _done wont gete called for 9 seconds.
function _start(data){
// Insert some kinda native magic loop
}
function _one(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(1);
}, 3000);
})
};
function _two(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(2);
}, 3000);
})
};
function _done(){
console.log('All done in 9 seconds)
}
(function(){
var work = ['_one', '_two', '_two'];
_start(work);
})();
Given the order is dicated by the array, you can use reduce to aggregate the promises into a chain
const _start = (...actions) => {
return actions.reduce((chain, action) => {
const func = this[action];
return chain.then(() => func());
}, Promise.resolve());
}
...
_start('_one', '_two', '_three').then(() => console.log('All done'));
See it in action - the example appends an extra then to the chain just to output any results from the promises (probably outwith the scope of this question but something you may have to consider if getting data back is required).
Update
Can see you intend on invoking _start from a different context in which the functions are declared, this is fine but you need to make sure you set the correct context before hand i.e.
const self = this;
(function() {
_start.bind(self)('_one', '_two', '_two');
})();
A function which creates a promise which sleeps:
const sleep = n => () => new Promise(resolve => setTimeout(resolve, n));
A function which sleeps after some input promise:
const sleepAfter = n => p => p.then(sleep(n));
A function which chains a bunch of promises, represented by functions:
const chain = (...promises) => promises.reduce((ret, promise) => ret.then(promise),
Promise.resolve());
Run a bunch of functions yielding promises, sleeping in between:
const _start = promises => chain(promises.map(sleepAfter(3000)));
Now just:
_start(_one, _two, _three).then(_done);
Try using this:
_one().then((firstResponse) {
return_two();
}) .then((secondResponse) => {
*second and first respone are already done*
});
Use promises then
_one().then((responseOne) => {
return _two();
}).then((responseTwo) => {
// _one & _two are done
});
Given i have a method that performs async operation and returns promise that gets resolve when that operation is done - how do i make sure that when called multiple times before that operation is done i get as a result same promise.
Edit when i call it after operation is done - i want to get new promise for current operation..
One option is to remember call ( memoize ) and eg track promise by a variable in outer scope
var p;
function test() {
if (p) return p;
p = new Promise(res) {
res();
p = null;
}
return p;
}
Any other nicer solutions?
The approach You're using here is called memoization and it's hard to come up with anything nicer.
What You might want to do is to split the tedious bits (save in outer scope, reuse, delete) from the function itself. Or even use a library:
import reusePromise from 'reuse-promise';
function test() {
return new Promise(function (res) {
res();
});
}
const reusableTest = reusePromise(test);
Full example
"use strict";
const reusePromise = require('reuse-promise').default;
let i = 0;
function test() {
return new Promise(resolve => {
setTimeout(() => resolve(i++), 100);
});
}
const reusableTest = reusePromise(test);
reusableTest().then(console.log).catch(console.err);
reusableTest().then(console.log).catch(console.err);
reusableTest().then(console.log).catch(console.err);
setTimeout(() => {
reusableTest().then(console.log).catch(console.err);
reusableTest().then(console.log).catch(console.err);
reusableTest().then(console.log).catch(console.err);
}, 200);
// output: 0 0 0 1 1 1
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.