0

My problem

I have an asynchronous method populate() that tries to do something, and if it fails, catches the error and calls another asynchronous method populateFromServer() (which can fail too). I call the first in a Promise.all() with a catch afterwards in case no attempt worked. However, .all() always trigger because of populate(), for some reason, although it should be caught. Here is a simplified version of my code (typescript):

abstract class Database {
  public static async populate() {
    try {
      await populateFromLocalFile();
    } catch (err) {
      await this.populateFromServer();
    }
  }

  private static async populateFromServer() {
    await fetchFromServer();  // Might fail eg. if there is no internet
  }
}

And somewhere else:

Promise.all([
  ChildDB1.populate(),
  ChildDB2.populate(),
  ChildDB3.populate(),
])
.then(() => /* population worked (either local or distant) */)
.catch(() => /* no population attempt worked */)

My code seems to get caught after the Promise.all when populate() fails, even though I caught it and populateFromServer() worked perfectly fine (I checked with logs). Why? How can I fix that?

What I tried

Returning Promise.resolve()

Someone suggested to return Promise.resolve() at the end of the catch block, but it doesn't fix the problem:

  public static async populate() {
    try {
      await populateFromLocalFile();
    } catch (err) {
      await this.populateFromServer();
      return Promise.resolve()
    }
    return Promise.resolve()
  }

Using .then

I also tried using the other way with .then but I still have that problem

abstract class Database {
  public static async populate() {
    await populateFromLocalFile()
      .then(() => doStuff())
      .catch(async () => {
          console.log('error happened here');
          await this.populateFromServer();
      });
  }

  private static async B() {
    await fetchFromServer();
  }
}
Biskweet
  • 130
  • 1
  • 9
  • 1
    Based on what your saying, it should work. I've a feeling `populateFromServer` is maybe not a Promise. – Keith Mar 20 '23 at 17:29
  • Does it work without `populateFromServer`? It throwing is the only reason I see that this can fail. https://replit.com/@knyzorg/FreshSickCallback#index.js – Slava Knyazev Mar 20 '23 at 17:34
  • @Keith `populateFromServer` is an asynchronous function that returns either `Promise.resolve()` or `Promise.reject()`. I might lack a bit of experience with subtilities with asynchronous programming in JavaScript but I believe it's a correct way to do it? @SlavaKnyazev I just tried without and it still fails. I really have no clue. Here is a [fiddle](https://jsfiddle.net/Biskweet/9hup368L/1/) – Biskweet Mar 20 '23 at 17:44
  • "*`populateFromServer()` worked perfectly fine*" - it probably didn't. So what's the error you are getting after the `Promise.all()`? Where does it come from? Log the errors that you caught, do some debugging. – Bergi Mar 20 '23 at 18:08
  • @Bergi the problem is that even when I comment out `populateFromServer` the code still goes into the Promise catch. I'm updating the fiddle with the rest of the code. – Biskweet Mar 20 '23 at 18:31
  • @Biskweet Then it's clearly something else, in a part of the code that you didn't show us yet – Bergi Mar 20 '23 at 19:26
  • @Bergi indeed it was another part of my code. Problem solved, and thank you for you help. – Biskweet Mar 20 '23 at 21:34
  • Using `Promise.resolve() or Promise.reject()` is very rarely the correct way to use promises in an `async` function. – Keith Mar 21 '23 at 10:49

1 Answers1

0

The problem was in the .then method of my Promise.all

Promise.all([
  ChildDB1.populate(),
  ChildDB2.populate(),
  ChildDB3.populate(),
])
.then(() => /* stuff */)  // <-- this is the part that failed silently
.catch(() => /* other stuff */)
Biskweet
  • 130
  • 1
  • 9
  • 1
    Using [`.then(…, …)` instead of `.then(…).catch(…)`](https://stackoverflow.com/q/24662289/1048572) might help to avoid this - you'd get an unhandled rejection instead of (unexpectedly) getting success handler exceptions handled by the error handler. – Bergi Mar 20 '23 at 21:40