0

If I add the keyword async to a function, it seems that I have to catch errors "in" that function. Sometimes it doesn't make sense to catch errors and I want to defer them to the caller as I may not know the context in which the function is called (e.g. is the caller doing res.json(e) or next(e), or neither)

Is there a way around this? So I can use async (in order to await inside the function) and defer errors to the caller?

Here is a really contrived example

https://codepen.io/anon/pen/OzEXwM?editors=1012

try {
    function example(obj = {}) {
        try {
            obj.test = async () => { // if I remove async keyword, it works, otherwise I'm forced to catch errors here
                //try{
                throw new Error('example error') // I know `example outer error` won't catch as the returned object loses the context
                //}catch(e){
                //  console.log('I do not want to catch error here'), I wan't to defer it to the caller
                //}  
            }
            return obj
        } catch (e) {
            console.log('example outer error')
        }
    }

    let doit = example()
    doit.test() // why doesn't 'outer error' catch this?

} catch (e) {
    console.log('outer error')
}

The script ran as is will give an Uncaught Exception. But if I remove the async keyword it works (yes, I know in this example, async is silly, it's just an example)

Why can't I catch the error when doit.test() is called?

Usually, I would just comply and rework, but in trying to explain to someone else this morning, I realized, I didn't really know the answer.

2 Answers 2

1

Why can't I catch the error when doit.test() is called?

Because it is async. By the time it has reached the throw error part the try catch block on the outside has already been executed and passed. There is nothing to throw to so to speak.

To fix this, since async and await are just syntactic sugar for Promises you just use it's catch callback. Your test() function is going to return a promise so just add a the callback onto the returned promise

doit.test().catch(()=>{ 
  console.log('Any uncaught exceptions will be sent to here now');
}); 

Demo

function example(obj = {}) {
  obj.test = async() => {
    throw new Error('example error')
  }
  return obj;
}

let doit = example()
doit.test().catch(e => {
  console.log('Caught an exception: ', e.message);
});

Sign up to request clarification or add additional context in comments.

1 Comment

Right, that makes sense.
1

If you want to catch error of test() function. You need to do await doit.test()

https://jsfiddle.net/1tgqvwof/

I wrapped your code in a anonymous function since await must be within async function

(async function () {
    try {
        async function example(obj = {}) {
            try {
                obj.test = async () => { // if I remove async keyword, it works, otherwise I'm forced to catch errors here
                    //try{
                    throw new Error('example error') // I know `example outer error` won't catch as the returned object loses the context
                    //}catch(e){
                    //  console.log('I do not want to catch error here'), I wan't to defer it to the caller
                    //}
                }
                return obj
            } catch (e) {
                console.log('example outer error')
            }
        }

        let doit = example()
        await doit.test() // why doesn't 'outer error' catch this?

    } catch (e) {
        console.log('outer error')
    }
})();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.