2

Please, look at the following code. Line 5: return ex.

When I call myFunc, I expect to see 'err' in the console, but I see 'yes' which means that outside of myFunc the error is not being captured. The error is not bubbling up.

Which makes sense because I'm not rethrowing the error doing: throw ex or using Promise.reject(ex).

My Question is: How to ensure the error is captured outside of my function without using the two methods mentioned above? Is there a way?

async function myFunc() {
    try {
        throw new Error();
    } catch (ex) {
        return ex;
    }
}

myFunc().then(() => console.log('yes')).catch(() => console.log('err'))
// 'yes'
  • 1
    it's not being "captured" because it's caught, and dealt with by the catch statement - there is no error condition any more – Jaromanda X Jul 19 '19 at 00:25
  • 4
    Like you mentioned, you have to re-throw the error or use Promise.reject - why don't you want to use either of those? – CertainPerformance Jul 19 '19 at 00:25
  • 3
    in this example, don't use try catch and `err` will be logged – Jaromanda X Jul 19 '19 at 00:26
  • What's the point of using `async` without `await`? If you use `async/await`, `.then()` isn't needed, correct? – zer00ne Jul 19 '19 at 00:35
  • I have to use try catch in my function, this is just an example of how I would call an external service, make sure it works, and if it doesn't, I will return my own Error object. I don't want to rethrow because rethrowing bundles the Error with the stack trace which I do not want. – user1867821 Jul 19 '19 at 00:38
  • 2
    There's many circumstances where you would use `async` without `await`, I'm not going to discuss this here because it's not the purpose of this ticket. – user1867821 Jul 19 '19 at 00:40
  • Given the promise chain is working correctly, what is the problem with stack tracing? Is the Error object's "stack" string property of potential use in solving the issue? – traktor Jul 19 '19 at 01:11
  • 2
    There's no way to be selective about which errors you wanna catch and which don't. If there's a catch, it will catch any kind of error. – MinusFour Jul 19 '19 at 01:39
  • 1
    Why do you want to avoid `return Proise.reject()` in the catch part? It works as you intend it to work – Philipp Jul 19 '19 at 07:27
  • Are you just curious whether there is a third way next to `throw` and `Promise.reject`, or do you have an [actual problem](https://meta.stackexchange.com/q/66377) with those? – Bergi Jul 19 '19 at 14:13
  • I prefer not to mix `async` syntax with `Promise` syntax. It's ugly and makes no sense if you using `async` then just use `async`. If you mix both, then you don't understand how `async` works! – user1867821 Jul 19 '19 at 15:39
  • Bergi, good question. I'm curious. But I guess there's no other way then to re-throw doing `throw ex` on catch – user1867821 Jul 19 '19 at 15:40
  • tracktor53, you make a good point. I've settled on re-throwing the error – user1867821 Jul 19 '19 at 15:45

3 Answers3

1

When using async functions, you can use the normal javascript try / catch to handle errors.

If you throw within an async function, the promise it returned will be rejected. If you return from an async function (like you did in your catch block), the promise will be resolved with the returned value (in your case the exception)

Here two examples how you can handle an async function that might throw:

// async function that might throw
async function funcThatThrows() {
  throw new Error("IT THROWS!");
}

// Exception Handling in other async functions
async function example1() {
  try {
    let result = await funcThatThrows();
    /* ... */
  } catch(e) {
    console.log("example1:", e.message);
  }
}

// Exception handling in non-async functions
function example2() {
  funcThatThrows()
    .then(result => { /* ... */ })
    .catch(err => console.log("example2:", err.message));
}

example1();
example2();

See Javascript Async/Await Error Handling for a detailed tutorial on async error handling :)

Turtlefight
  • 9,420
  • 2
  • 23
  • 40
0

The best way is to do this:

async function myFunc() {
    try {
        throw new Error();
    } catch (ex) {
        throw ex;
    }
}
Fabio Costa
  • 213
  • 3
  • 8
  • There is no need to catch and rethrow the exception ```async function myFunc() { throw new Error(); } ``` does exactly the same – Turtlefight Jul 20 '19 at 12:10
0

I had an attempt at answering the question but ended up rewriting my whole answer. At one point, I deleted my answer.

As you already stated in the question, throw ex or Promise.reject(ex) are the only ways.

When I use async function in my application, I usually do so as a means to migrate away from Promise chaining and dropping then and catch. It's really odd that you mix async function but call it with Promise, then and catch syntax.

Actually, I think it's dangerous to mix it as indicated here: JavaScript Promises - reject vs. throw

If you indulge me, I want to rewrite your caller using async function and await:

async function myFunc() {
    throw new Error("Some Error!");
}

( async function () {
  try {
    await myFunc();
    console.log("yes");
  } catch (err) {
    console.log("err: ", err.message);
  }
} )();

This syntax is similar to its synchronous counterpart which infers we ought to use throw:

function myFunc() {
    throw new Error("Some Error!");
}

( function () {
  try {
    myFunc();
    console.log("yes");
  } catch (err) {
    console.log("err: ", err.message);
  }
} )();
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75