Background
If you are a Js developer, you probably have used async
and await
, and you love them.
No more callback hell or .then
chains. Just like writing a synchronous program.
Util you run into UnhandledPromiseRejectionWarning
or Uncaught (in promise) Error
You begin to wrap every piece of code using try.. catch..
, but that seems a lot of work.
But I've got good news, you can write a custom async function error handler:
Solution
const asyncHandler = fn => async (...args) => { try { await fn(...args); } catch (err) { console.log(err); } };
It takes all types of functions with any number of arguments.
use it like this:
const asyncHandler = fn => async (...args) => { try { await fn(...args); } catch (err) { console.log(err); } }; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const yourFunction = async () => { await sleep(2000); throw 'something wrong'; return 'success'; } (async ()=> { await yourFunction(); // will cause Uncaught error await asyncHandler(yourFunction)(); // will handle the error properly })();
Return values
Of course when you need the result of the async function, you can:
const asyncHandler = fn => async (...args) => { try { return await fn(...args); } catch (err) { console.log(err); } }; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const yourFunction = async () => { await sleep(2000); // throw 'something wrong'; return 'success'; } (async ()=> { const result = await asyncHandler(yourFunction)(); //will handle the error properly console.log(result); // => 'success' })();
Custom error handling
if you need some custom error handling, for example, to use it in express.js
you can do simply by adding some of your custom logic
const asyncHandler = fn => async (...args) => { try { await fn(...args); } catch (err) { logger.error(err); const resFn = args.find(arg => arg.name === 'res'); if (resFn) { let errors = { message: 'Internal Sever Error', error: err }; if (err instanceof mongoose.Error.ValidationError) { errors = { message: 'Mongoose Model Validation Error', error: err }; } if (err instanceof mongoose.mongo.MongoError) { errors = { message: 'MongDB Error', error: err }; } resFn.status(500).json(errors); } } };
later you use it in express routers like this:
router.get('/item', asyncHandler(async (req, res) => { // router logic here }) )
Top comments (2)
Can I pass a custom error object to the asyncHandler from with the '/item' route
Sure, you can throw custom error, and handle it in asyncHandler, just make sure you have a way to identify it.