Javascript wait for condition to be true using promises
10,846
Solution 1
You have to return
a promise:
function waitForCondition(conditionObj) {
return new Promise(resolve => {
var start_time = Date.now();
function checkFlag() {
if (conditionObj.arg == conditionObj.test) {
console.log('met');
resolve();
} else if (Date.now() > start_time + 3000) {
console.log('not met, time out');
resolve();
} else {
window.setTimeout(checkFlag, 1000);
}
}
checkFlag();
});
}
async function run() {
console.log('before');
await waitForCondition({arg: '1', test: '1'})
console.log('after');
}
run();
I refactored your code a bit. To get the current time, use Date.now()
. And you should be OK with calling resolve
without a timeout of 1 millisecond.
Solution 2
I believe what you are really looking for is
function waitForCondition(conditionObj) {
var start_time = new Date().getTime()
async function checkFlag() {
if (conditionObj.arg == conditionObj.test) {
console.log('met');
// return something?
} else if (new Date() > start_time + 3000) {
console.log('not met, time out');
// throw some error?
} else {
await new Promise(resolve => setTimeout(resolve, 1000));
return checkFlag();
}
}
return checkFlag();
}
or with a loop instead of the recursion
async function waitForCondition(conditionObj) {
var start_time = new Date().getTime()
while (true) {
if (conditionObj.arg == conditionObj.test) {
console.log('met');
break; // or return
}
if (new Date() > start_time + 3000) {
console.log('not met, time out');
break; // or throw
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
Related videos on Youtube
Author by
T Mack
I am developing an application called Somiibo. It's a social media bot that automates your digital and internet marketing. Go check it out if you want to see how it can help you streamline your promotion :)
Updated on September 14, 2022Comments
-
T Mack over 1 year
I am struggling to make a simple waiting function in my program. I want to use promises and async await if possible. What I have so far:
function waitForCondition(conditionObj) { var start_time = new Date().getTime() function checkFlag() { if (conditionObj.arg == conditionObj.test) { console.log('met'); return new Promise(resolve => setTimeout(resolve, 1)); } else if (new Date() > start_time + 3000) { console.log('not met, time out'); return new Promise(resolve => setTimeout(resolve, 1)); } else { window.setTimeout(checkFlag, 1000); } } checkFlag(); } async function run() { console.log('before'); await waitForCondition({arg: '1', test: '1'}) console.log('after'); } run();
It should check every 1 second for a maximum time of 3 seconds. The console should look like this:
'before' 'met' 'after'
-
PeterMader over 6 yearsBut just adding a
return
isn't enough.checkFlag()
will return undefined if the condition isn't met yet. -
Bergi over 6 yearsYes, but please don't write the promise logic like that. You should promisify
setTimeout
and nothing else. -
T Mack over 6 years@petermader thank you for the amazing answer this is exactly what I was trying to do.
-
Hans Bouwmeester almost 5 years@Bergi, I'm new to this. It would be helpful if you could explain why?
-
Hans Bouwmeester almost 5 years+1, though in my opinion it's not a good idea to use recursion here (as there's no need to place anything on the stack). I think the 2nd example is the way to go.
-
Bergi almost 5 years@HansBouwmeester I posted the recursive implementation mostly because the OP had started with a recursive idea.
-
Bergi almost 5 years@HansBouwmeester Basically because you are loosing all the benefits of promises with that, like chainability and implicit error handling. Apart from not catching exceptions, the non-promise code becomes harder to modify when you want to add another asynchronous (promise) call, you are more likely to fall for the
Promise
constructor antipattern.