3
\$\begingroup\$

I want to make a function to retry calling callback n times until it return TRUE;

Here's my current code:

function RetryX(callback, delay, retries) {

    (function wait() {

        if( callback() !== true && --retries > 0 ){
            setTimeout(wait, delay);
        }

    }());

}

Question:

  1. Is it correct way to do it?
  2. Is there any way to optimize it?
  3. Can it be modified to pass jslint? currently it shows "unexpected --retries"
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Super short review;

  • Pure nitpicking, but to me, you try the first time, and retry afterward. This means that a retry of 3 would guarantee up to 4 calls.
  • I would not create wait but just call the retryX function
  • JavaScript is lowerCamelCase so RetryX -> retryX, personally I would go for tryN

So probably I would run something like this;

function tryN(callback, delay, tries) {
  
  if(tries && callback() !== true){
    setTimeout(tryN.bind(this, callback, delay, tries-1), delay);
  }
}

function NI(){
 console.log("NI!");
 return false;
}


tryN(NI, 1000, 3);

To be clear, if a funny coder passes -1 to this function then you are in an infinite try. Guard for this if you see the need.

\$\endgroup\$
-1
\$\begingroup\$

Promise to poll.

Best to poll for state using a promise. As it provides syntax for errors (timeouts) , chained polling queries using async / await and more.

Example

The code below shows the most basic example.

  • poll(call, delay, timeout) returns a promise to poll call every delay ms until timeout ms have passed. If it times out the promise is rejected.

  • waitForIt is an async example that waits for a random true.

  • pollingFunc Is called once every delay and shows the current time elapsed, and returns a random bool state (true or false)

  • Last bit of code starts the polling and handles the results when and if ready.

  • The example passes the time around. This is just for the example and not required.

function poll(call, delay, timeout) {
    return new Promise((done, timedOut) => {
        const start = performance.now();
        const tick = () => {
            const t = performance.now() - start;
            if (call(t)) { done(t) }
            else if (t > timeout) { timedOut(t); }
            else { setTimeout(tick, delay); }
        };
        tick();
    });
}
const pollingFunc = (time) => {
    console.log("Polling: " + time.toFixed(0) + "ms");
    return Math.random() < 0.05;
}    
async function waitForIt() {
    return poll(pollingFunc , 200, 2000);
}
waitForIt()
  .then(t => console.log("Completed in: " + t.toFixed(0) + "ms"))
  .catch(t => console.log("Error Timed-out: " + t.toFixed(0) + "ms"));

// Or just 
/*
poll(pollingFunc , 200, 2000)
  .then(t => console.log("Completed in: " + t.toFixed(0) + "ms"))
  .catch(t => console.log("Error Timed-out: " + t.toFixed(0) + "ms"));
*/

         
            

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.