Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to throw exception from async function

Tags:

I have an async function that I expect to throw exception on failure. However something seems to preventing this:

by omitting the try catch blocks I expect an exception to be thrown which I want to handle outside of the function.

The actual result I get is somewhat confusing:

(node:10636) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): E11000 duplicate key error index.

(node:10636) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

async f(obj) {     await db.collection('...').save(obj); } 

I get the same result when I try to catch the exception and throw something else instead:

async f(obj) {     try {         await db.collection('...').save(obj);     } catch(e) {         throw e.message;     } } 

The function is called from a try block, so don't see how this is an Unhandled Promise.

I am trying to use f as a parameter of another function:

g(obj, handler) {     try {         handler(obj);     } catch(e);         ...     } }  g(objToSave, f); 
like image 468
user1063963 Avatar asked Mar 21 '17 11:03

user1063963


People also ask

How do you handle exceptions in async methods?

Implement try-catch within the function This is the solution to catch exceptions in asynchronous methods. Have a look at the following code. If you look closely inside the ShowAsync() function, then you will find we have implemented a try-catch within Task. run().

What happens if an exception is thrown within an asynchronous method?

When an exception occurs in an async method that has a return type of Task or Task, the exception object is wrapped in an instance of AggregateException and attached to the Task object. If multiple exceptions are thrown, all of them are stored in the Task object.


1 Answers

async f(obj) {     try {         await db.collection('...').save(obj);     } catch(e) {         throw e.message;     } } 

The function is called from a try block, so don't see how this is an Unhandled Promise.

What is unhandled here is the rejection of a promise returned by the f() function, not by the .save() method. So this will not cause that problem:

async f(obj) {     try {         await db.collection('...').save(obj);     } catch(e) {         console.error(e.message);     } } 

Throwing an exception in async function always rejects the promise that is returned by that function.

To catch the exception you either have to do this in another async function:

try {     asyncFunc(); } catch (err) {     // you have the error here } 

or you can add a rejection handler explicitly:

asyncFunc().catch(err => {     // you have the error here }); 

If you are catching the exception and throwing another exception then you get the same problem, just in a different function.

You either have to add a promise rejection handler and not throw an exception or return a rejected promise there - or run that function in another async function that handles the exception instead of rethrowing the same or new exception.

To sum it up: Every async function returns a promise. Every promise needs to have a rejection handler.

The rejection handler is added using a two-function .then() or with .catch(), or with try { await asyncFunction(); } catch (err) { ... }

When you have a promise rejection with no rejection handler, you will get a warning in older versions of Node and a fatal error in newer versions of Node - see this answer for more details:

  • Should I refrain from handling Promise rejection asynchronously?
like image 154
rsp Avatar answered Sep 25 '22 23:09

rsp