0

I want to. retry my js dynamic import if it failed. I found 1 solution here - How to manually load webpack async chunks, when any dynamic import fails to load file?

function retry(fn, retriesLeft = 5, interval = 1000) {
  return new Promise((resolve, reject) => {
    fn()
      .then(resolve)
      .catch((error) => {
        setTimeout(() => {
          if (retriesLeft === 1) {
            // reject('maximum retries exceeded');
            reject(error);
            return;
          }

          // Passing on "reject" is the important part
          
          //HOW DOES THIS PART OF CODE WORKS? WHY WE NEED THEN CALLBACK WITH resolve, reject callbacks?
          retry(fn, retriesLeft - 1, interval).then(resolve, reject);
        }, interval);
      });
  });
}

(we called retry function which return new promise) HOW DOES THIS PART OF CODE WORKS? WHY WE NEED ".then" CALLBACK WITH resolve, reject callbacks?

why we need

.then(resolve, reject);

this construction?

Is it really necessary to update the state (rejected) of the promise to work from outside?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
user469485
  • 55
  • 6
  • The setTimeout of 1000 ms needs a callback, because it "breaks" the Promise chain, and the code - as it is set up - throws an error after five retries. The `.then(resolve, reject)` is the only thing that ties the setTimeout to the previous Promise. – Rickard Elimää Oct 20 '22 at 19:10
  • Your code has the [Explicit Promise Construction Antipattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it)! (Only the `setTimeout` part should be wrapped in `new Promise`) – FZs Oct 20 '22 at 19:12
  • @FZs, How can i change it if i want to use it with react.lazy? – user469485 Oct 20 '22 at 19:18
  • Why not just use dynamic `import()`? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#importing_on-demand_in_response_to_user_action – Rickard Elimää Oct 20 '22 at 19:19
  • @RickardElimää, Thank You, but i do not fully understand, does a promise change its status if it is rejected at least once? – user469485 Oct 20 '22 at 19:20
  • @RickardElimää, i want to have retry load logic – user469485 Oct 20 '22 at 19:21
  • No, but you can create a method that does dynamic imports, and then just call that method again in a catch. – Rickard Elimää Oct 20 '22 at 19:21
  • 1
    @RickardElimää That's probably what `fn()` does in OP's code. – FZs Oct 20 '22 at 19:24
  • @RickardElimää, i want to use it declaratively (as React component) this function will be in react component – user469485 Oct 20 '22 at 19:24
  • @user469485 You can just wrap a call to `retry` in `React.lazy`, and you should be good. – FZs Oct 20 '22 at 19:25

1 Answers1

0

Reduce the clutter to see the core logic. Without forwarding the resolve/reject functions in some way, only the top-level call will resolve via .then.

function retry(fn) {
  return new Promise((resolve, reject) => {
    fn()
      .then(resolve)
      .catch((error) => {
        /* this call does not return to catch. data is lost */
        retry(fn)
      });
  });
}

retry(foo).then(/* */)

As other have pointed out, setTimeout inside a promise handler is dangerous because throwing in the callback does not bubble into the promise chain.

OFRBG
  • 1,653
  • 14
  • 28