Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would you try-catch around a promise? Does that catch the promise's error?

I stumbled upon some code that looked off to me:

try {
  somePromise()
    .then(res => console.log(res));
} catch (err) {
  console.error(err);
}

If some somePromise() fails, would this not get caught, and the app would crash? Does this try-catch even do anything?

Should be this, correct?:

  somePromise()
    .then(res => console.log(res))
    .catch(err => console.error(err));
like image 938
atkayla Avatar asked Apr 30 '17 02:04

atkayla


People also ask

How do you catch an error in a promise?

Inside the promise, the catch() method will catch the error caused by the throw statement and reject() . If an error occurs and you don't have the catch() method, the JavaScript engine issues a runtime error and stops the program.

Can you use try catch in promise?

You cannot use try-catch statements to handle exceptions thrown asynchronously, as the function has "returned" before any exception is thrown. You should instead use the promise. then and promise. catch methods, which represent the asynchronous equivalent of the try-catch statement.

What happens if one of the promises in promise all rejects with an error?

It resolves once all promises in the array resolve, or reject as soon as one of them rejects. In other words, it either resolves with an array of all resolved values, or rejects with a single error.

Does promise all throw error?

As we can see in the output above, even though the promise2 function throws an error, the Promise. all() method does not get rejected, and the browser throws an unhandled error.


2 Answers

TL;DR - If a function that returns a promise throws an exception before returning the promise then that exception would have to be caught in a regular try-catch block.

Consider this function

function asyncAdd(x,y){
   if(x === 2){
        throw new Error("good old exception")
   }else if(x === 1) { 
      return Promise.reject("fancy exception")
   }

   return Promise.resolve(x+y)
}

This would print "Try caught good old exception"

try{
  asyncAdd(2,10).then(x =>console.log("result", x)).catch(y => console.error("Promise caught", y));
}catch (e){
  console.error("Try caught", e);
}

This would print "Promise caught fancy exception"

try{
  asyncAdd(1,10).then(x =>console.log("result", x)).catch(y => console.error("Promise caught", y));
}catch (e){
  console.error("Try caught", e);
}
like image 50
Karthik Avatar answered Oct 14 '22 14:10

Karthik


If you're dealing with a rubbish function that could return a Promise or throw an Error, that is truly unfortunate. I would recommend a generic tryCatch utility like below to deal with the offensive function.

const badFunction = x =>
{ if (x)
    return Promise.resolve(x)
  else
    throw Error('this is a bad function')
}

const tryCatch = (f, ...args) =>
  new Promise(r => r(f(...args)))

tryCatch(badFunction, 1)
  .then(console.log, console.error)
// 1

tryCatch(badFunction, 0)
  .then(console.log, console.error)
// Error: this is a bad function

Fix it if you can

If the rubbish function is under your control to fix, then I would recommending writing it something like this

const goodFunction = x =>
{ if (x)
    return Promise.resolve(x)
  else
    return Promise.reject(Error('this is a good function'))
}

goodFunction(1).then(console.log, console.error)
// 1

goodFunction(0).then(console.log, console.error)
// Error: this is a good function

Uncaught errors in .then-chained functions

That's not to say that sometimes we still might encounter a situation where you will need to use a function that could throw. For example, if we then a function that can throw – JSON.parse in this case - Promises are already equipped to handle this in a convenient way; the thrown Error will be captured inside of a rejected promise

const goodFunction = x =>
  Promise.resolve(x)
  
goodFunction('"abc"')
  .then(JSON.parse)
  .then(console.log, console.error)
  // 'abc'

goodFunction('abc')
  .then(JSON.parse)
  .then(console.log, console.error)
  // 'Unexpected token a in JSON at position 0'

Uncaught errors in Promise executor

If a function throws an error in your Promise executor, don't worry, the error will be contained in an automatically rejected promise -

const okFunction = x =>
  new Promise(resolve => resolve(JSON.parse(x)))

okFunction('"abc"').then(console.log, console.error)
// 'abc'

okFunction('abc').then(console.log, console.error)
// Error: Unexpected token a in JSON at position 0
like image 2
Mulan Avatar answered Oct 14 '22 12:10

Mulan