Home > Software engineering >  How to catch an error thrown in an un-awaited async function inside try/ catch?
How to catch an error thrown in an un-awaited async function inside try/ catch?

Time:12-14

I'm hoping someone can suggest a better method for what I'm trying to achieve.

While performing a rather long and complicated webflow using puppeteer, occasionally an error will occur that disrupts the actions I'm trying to take on the page. There's nothing I can do about it in these situations other than return a useful error. However it doesn't happen often enough to explicitly wait and try to catch it after each step in my code.

The solution I have is:

async function runCode() {
    try {
         const page = browser.open(url)
          listenForError(page)
          await longWebFlow()
    } catch (err) {
      return err.message
    }
}

async function listenForError(page) {
  await page.waitForXPath(errorMessageXPath)
  throw new Error('Error found!')
}

try {
    await runCode()
} catch (err) {
console.log(err.message)
// should print('Error found')
}

Obviously, the unawaited listenForError call won't be caught in the try/catch, but I also cant await the call, or else I'll never get to the main part of the code.

The code works to short-circuit the process and return, since the error occurred, but how can I refactor this to catch the error message?

CodePudding user response:

It seems like you want to wait until either the error is thrown or the longWebFlow() finishes - basically doing both concurrently. That's a perfect use case for promises with Promise.race:

async function runCode() {
    const page = browser.open(url)
    await Promise.race([
        listenForError(page),
        longWebFlow(),
    ]);
}

You could also use Promise.all if you made longWebFlow cancel the listenForError and fulfill the promise.

Either way, since you can properly await the promises now, the error also will be caught in the try/catch, as it should.

CodePudding user response:

If you can't await the async operation then the only other "follow up" is with callbacks like .then() and .catch(). For example, you can catch the error here:

listenForError(page).catch(e => console.log(e));

This won't await the operation, it's just supplying a callback for whenever that operation fails at whatever point in the future.

  • Related