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));
  }
}
Share:
10,846

Related videos on Youtube

T Mack
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, 2022

Comments

  • T Mack
    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
    PeterMader over 6 years
    But just adding a return isn't enough. checkFlag() will return undefined if the condition isn't met yet.
  • Bergi
    Bergi over 6 years
    Yes, but please don't write the promise logic like that. You should promisify setTimeout and nothing else.
  • T Mack
    T Mack over 6 years
    @petermader thank you for the amazing answer this is exactly what I was trying to do.
  • Hans Bouwmeester
    Hans Bouwmeester almost 5 years
    @Bergi, I'm new to this. It would be helpful if you could explain why?
  • Hans Bouwmeester
    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
    Bergi almost 5 years
    @HansBouwmeester I posted the recursive implementation mostly because the OP had started with a recursive idea.
  • Bergi
    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.