0

I have a function that makes a server call and returns a promise, like so:

function postToServer(url, body) {
  let xhr = new XMLHttpRequest();
  xhr.open(`POST`, url, true);
  xhr.setRequestHeader(`Content-type`, `application/json`);

  return new Promise((resolve, reject) => {
    xhr.onload = () => {
      if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
        resolve();
      } else {
        reject(xhr.status);
      }
    };

    xhr.send(body);
  });
}

This seems to work just fine for my case. However, the problem comes when I want to retry that call on failure. I have a different function that performs this process:

function postToServerAndRetryOnFail(url, body, failedAttempts = 0) {
  return new Promise((resolve, reject) => {
    postToServer(url, body).then(() => {
      resolve();
    }, statusCode => {
      failedAttempts++;

      if(failedAttempts <= maxAttempts) {
        wait(intervalBetweenAttempts).then(() => {
          postToServerAndRetryOnFail(url, body, failedAttempts);
        });
      } else {
        reject(statusCode);
      }

    });
  });
}

What I would expect to happen here is, when the request fails, it tries until it reaches the maximum number of attempts, at which point it returns a rejection. Note that the function does behave as expected for successful requests.

What is actually happening is that it fails, retries, fails, ... (as expected) until it reaches the maximum number of tries. Then, instead of rejecting, I just get uncaught exception: 404 with no line number or stack trace. What's going on here? Why isn't it just rejecting as normal?

Ian
  • 5,704
  • 6
  • 40
  • 72
  • Are you sure it says "uncaught exception", not "unhandled rejection"? – Bergi Jun 01 '18 at 16:40
  • Very related: https://stackoverflow.com/q/50295615/1048572 - avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it) in `postToServerAndRetryOnFail`! – Bergi Jun 01 '18 at 16:41
  • @Bergi yes, I copied the error directly – Ian Jun 01 '18 at 16:42
  • 1
    "*Note that the function does behave as expected for successful requests.*" - I don't think so. Have you waited for the result? – Bergi Jun 01 '18 at 16:44
  • @Bergi If I make the URL intentionally incorrect such that it returns a 404, then my problem occurs. If I make it correct such that it returns 200, then the promise resolves as expected. – Ian Jun 01 '18 at 16:48
  • I mean when you get a 404 on first attempt and a 200 on the second one, it doesn't work. – Bergi Jun 01 '18 at 16:51
  • Then it doesn't throw that error, but the promise doesn't resolve. Why is that? – Ian Jun 01 '18 at 16:53
  • Because you never `resolve` the promise in that case. As I said, avoid the `Promise` constructor antipattern - check the links. – Bergi Jun 01 '18 at 16:56

0 Answers0