Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can async with fetch poll until a condition is met? (survive rejection)

Using fetch API and async/await, is it possible to continue polling indefinitely, regardless of availability of a URL? I anticipate that a URL might become available eventually, so I want to keep trying until a condition is met. Tried to come up with a minimum viable code sample and I'm not sure I pulled it off:

// this is just a placeholder. It will eventually be a function 
// that evaluates something real. 
// Assume validContinue gets updated elsewhere.      
function shouldContinue() {
    return validContinue;
}
      
async function wonderPoll(someUrl) {

  // just a delay mechanism
  function wait(ms = 1000) {
    return new Promise(resolve => {
      setTimeout(resolve, ms);
    });
  }

  // the actual individual poll
  async function pollingFunction(url) {

    const response = await fetch(url, {
      cache: 'no-store'
    });

    if (response.ok) {
      return response;
    } else {
      Promise.reject(response);
    }

  }

  // allegedly keep polling until condition is met. 
  // But the rejected Promise is breaking out!
  while (shouldContinue()) {
    await wait();
    result = await pollingFunction(someUrl);
  }
  
  // when the fetch hits a rejected state, we never get here!
  console.log('done with the while loop, returning last successful result')

  return result;
}

const sampleUrl = 'https://get.geojs.io/v1/ip/country.json?ip=8.8.8.8';
const sampleUrl2 = 'http://totallybroken_fo_sho';

// swap the URL to test
wonderPoll(sampleUrl)
  .then((result) => {
    console.log('got a result', result)
  })
  .catch((err) => {
    console.log('got an error', err)
  });

I see what's happening (I think). The parent call ultimately executes the polling function, which rejects on the Promise. The condition to continue is still theoretically met, but the rejection breaks out of the While loop and sends to rejection directly up. This propagates all the way up to the catch method of the original/initial Promise. It doesn't even hit any code that would have come after the While loop in the case of resolved Promises.

What I don't know is how to prevent that from happening. I think I don't understand the syntax for intercepting and resolving the promise. When I replace Promise.reject in the response parser with Promise.resolve(response), it still ends up rejecting up to the top.

If the URL I provide is valid, it will continue until the condition is no longer met.


Here's a fiddle: https://jsfiddle.net/gregpettit/qf495bjm/5/

To use the fiddle, the "stop" button simulates the condition being met, and I've provided two different URLs that have to be manually swapped (by passing someUrl or someUrl2) to test.

Expected results:

  • with good URL, continuous polling (will have to dig into network in dev tools) until condition is met (by pressing Stop!) and then the calling function's 'then' can show the result.
  • with bad URL, continuous polling until condition is met, and then calling function's 'catch' shows the error

Actual results:

  • positive test case is OK
  • negative test case goes directly to the catch
like image 798
Greg Pettit Avatar asked Nov 26 '25 09:11

Greg Pettit


1 Answers

You can try…catch it to prevent breaking out of loop.

while (shouldContinue()) {
  try {
    await wait();
    result = await pollingFunction(someUrl);
  } catch (e) {}
}
like image 163
hackape Avatar answered Nov 27 '25 21:11

hackape



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!