4

Sometimes I have a code in try-catch-finally block when finally branch does some cleanup code which may throw an Error. An error in the finally branch suppresses a possible error in the main branch. I want exactly the opposite: see an error from the main branch always and an error from the finally branch only when the main branch proceeds without an error. I have came up with solution:

let thrownError = false;
try {
    doMainCode();
} catch (err) {
    thrownError = true;
    throw err;
} finally {
    try {
        doCleanUpCode();
    } catch (err) {
        if (!thrownError)
            throw err;
        console.error("Suppressed finally error", err);
    }
}

Which is cumbersome. Is there any simpler way how to change error precedence in try-catch-finally block?

xmedeko
  • 7,336
  • 6
  • 55
  • 85
  • 1
    Besides writing a function (e.g. `noThrowWrapper`) to which you pass `doCleanUpCode`, and which would call that function and catch the possible error internally, or changing your `doCleanUpCode` to not throw there is not much you can do. – t.niese Apr 25 '23 at 07:23

1 Answers1

2

The usual approach I've seen here, for better or worse, is to just always suppress errors in the finally (dumping them to the console or a secondary logging stream or similar).

For places you don't want to do that, you could use a utility function to wrap your code to make it less cumbersome:

tryFinally(
    () => {
        // ...do main code...
    },
    () => {
        // ...do cleanup code...
    }
);

Yes, that does involve a layer of creating and calling functions where you didn't have one before, but modern JavaScript engines are very fast at that, it's not likely to cause a performance issue. (And if it does, you can address the specific places where it does.)

The tryFinally utility function would be responsible for handling the error stuff. Here's a quick sketch of an implementation:

function tryFinally(work, cleanup) {
    try {
        work();
    } catch (err) {
        try {
            cleanup();
        } catch (cleanupError) {
            console.error("Suppressed finally error", cleanupError);
        }
        throw err;
    }
    cleanup();
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875