-1

I was wondering why the try-catch block couldn't catch the promise rejected from foo.

Frustrated, need help. Thanks in advance.

function addTask(task) {
  setTimeout(() => {
    task.resolver()
  }, 1000)
}

function foo() {
  return new Promise((resolve, reject) => {
    const task = {
      resolver: function() {
        reject('task failed')
      }
    }
    addTask(task)
  })
}

function test() {
  try {
    foo()
  } catch (e) {
    console.error(e)
  }
}

// Uncaught (in promise) task failed
test()
xiyu
  • 11
  • 3
  • 4
    afaik try/catch only works with promises when using async/await syntax – evolutionxbox Jul 15 '22 at 08:55
  • barring special syntax 1) foo returns immediately; 2) try block only has foo call, so it also completes immediately. By the time promise is rejected, it should be intuitive that you're not in bounds of try/catch block anymore – Coderino Javarino Jul 15 '22 at 09:00

4 Answers4

0

It's the same reason that if you had:

const result = foo();

Then you would have a promise stored in result and not the settled value of the promise.

The asynchronous code is started, then the calling function continues.

Sometime later the promise is rejected, but by then it is too late for the code in test() to catch it.


If you had awaited foo(), which would require that test() be async, then it would be caught.

Otherwise you could need to use foo().catch(...).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

Promises are asynchronous but you are not awaiting. It means code continues. So you have to await or you have to use then().catch(). Something like this:

function addTask(task) {
  setTimeout(() => {
    task.resolver()
  }, 1000)
}

function foo() {
  return new Promise((resolve, reject) => {
    const task = {
      resolver: function() {
        reject('task failed')
      }
    }
    addTask(task)
  })
}

function test() {
  foo().then(console.log).catch(console.error);
}

// Uncaught (in promise) task failed
test()
Jax-p
  • 7,225
  • 4
  • 28
  • 58
0

To simplify your example:

function foo() {
  return new Promise((resolve, reject) => setTimeout(reject, 1000))
}

function test() {
  try {
    foo()
  } catch (e) {
    console.error("Error");
    return;
  }
  console.log("OK!");
}

test()

will print "OK!" indeed have Node.js raise an UnhandledPromiseRejection, as that foo() invocation is just "throwing away" the promise result value. The catch() would only catch synchronous exceptions, not promise rejections.

Turning the function into async function test() and awaiting on foo() will correctly output Error and no unhandled rejection.

AKX
  • 152,115
  • 15
  • 115
  • 172
0

Add await before foo() call and async before test function declaration

like below

  setTimeout(() => {
    task.resolver()
  }, 1000)
}

function foo() {
  return new Promise((resolve, reject) => {
    const task = {
      resolver: function() {
        reject('task failed')
      }
    }
    addTask(task)
  })
}

async function test() {
  try {
   await foo()
  } catch (e) {
    console.error(e)
  }
}

// Uncaught (in promise) task failed
test()`
rohit.bels
  • 94
  • 1
  • 6