CodeMonkey
CodeMonkey

Reputation: 12424

Wait until an external operation completes with setInterval before finishing

I got a JS code that simply activates a method. This method invokes an HTTP request which is causing some remote process to begin. I then need to check every 5 seconds if the remote process ended with a timeout of 5 minutes, after which I need to stop the waiting and throw an error if the timeout had expired, otherwise I need to simply log the result and complete the method.

What I'm not sure is how do I stop the execution of the main method until I get the response so I can have a value to log. This is what I got so far:

(async function(param) 
{
    ...
    var res = await fetch(...); //activate the remote proccess
    var textAnswer = await res.text();
    var infoObj = JSON.parse(textAnswer);
    startChecks(infoObj.info.id); // this is the method which I need to await on somehow 
}("paramValue");

async function startChecks(id)
{
    var startTime = new Date().getTime();
    intervalId = setInterval(checkStatus, 5000, id, startTime);
    
}

async function checkStatus(id, startTime)
{
  //if more than 5 minutes had passed
  if(new Date().getTime() - startTime > 300000) 
  {
      clearInterval(intervalId);
      throw new Error("External pipeline timeout expired");
  }
  var res = await fetch(...); //check remote process
  var ans = await res.text();
  var obj = JSON.parse(ans);
  if(obj.finished) clearInterval(intervalId);
 }

Like I said, what I want to achieve is that my main function won't end until all intervals are done with either the error thrown or the process finishes. How can I achieve that?

Upvotes: 0

Views: 340

Answers (1)

t.niese
t.niese

Reputation: 40852

You would create a helper function that executes your function in given intervals until it resolves to something different than undefined. But only for the maximum amount of time.

This could look something like this:

// helper to wait for time milliseconds
async function sleep(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}

async function repeatedExecution(callback, interval, timeout) {
  // get start time
  const start = Date.now();

  // repeat as long the start time + timout is larger then the current time
  while (start + timeout > Date.now()) {
    // get a promise that resolves in interval seconds
    let sleeper = sleep(interval)

    // execute the callback
    let res
    if (res = await callback()) {
      // if the callback returns something truthy return it
      return res;
    }
    // wait until time for interval ends and then continue the loop
    await sleeper;
  }

  // if we reach this point we timed out
  throw new Error('timed out');
}


async function run() {
  /*
   var res = await fetch(...); //activate the remote proccess
   var textAnswer = await res.text();
   var infoObj = JSON.parse(textAnswer);
  */


  try {
    let result = await repeatedExecution(() => {
      /*
        var res = await fetch(...); //check remote process
        var ans = await res.text();
        var obj = JSON.parse(ans);
      
        if(obj.finished) {
          return true
        }
      */
    }, 1000, 3000);

    // do something on success
  } catch (err) {
    // handle the error (timeout case)
    console.error(err)
  }

}

run();

Upvotes: 1

Related Questions