Jeflopo
Jeflopo

Reputation: 2262

How to properly control execution flow Javascript Exception Handling

In the real code I fetch accounts from an SQL Database. Then, for every account of accounts I call some methods a(), b(), c().

What I want Is that If for any reason an error (an exception) occurs while I'm calling a(), b(), c(), the execution halts and continue with the next iteration in the loop, that is, with the next account.

So, given that sample code:

const accounts = ['a1', 'a2', 'a3']

async function a() {
    await console.log('A');
}
async function b() {
    await console.log('B');
    throw new Error('B throws Error');
}
async function c() {
    await console.log('C');
}

async function main() {
    for (const account of accounts) {
        try {
            await a();
            await b();
            await c();
        } catch(e) {}
    }
}

main();

a() and b() Will get called, givin this output:

A
B
A
B
A
B

Then, If I add a try/catch in b()

async function b() {
    try {
        await console.log('B');
        throw new Error('B throws Error');
    } catch(e) {

    }
}

When running that code I would get:

A
B
C
A
B
C
A
B
C

Despite an exception was thrown in b(), but c() got also executed due to the try/catch...

My question is:

If I can't get the application to a reliable state in the catch... Is there a way that I can keep using try/catch-s in the inner methods but halting the execution so c() won't get executed ?

ps. If the way I'm using exceptions is just wrong. Would you help to shed some light to a correct usage ?

Upvotes: 1

Views: 121

Answers (1)

jfriend00
jfriend00

Reputation: 708046

If I can't get the application to a reliable state in the catch... Is there a way that I can keep using try/catch-s in the inner methods but halting the execution so c() won't get executed ?

Yes, just rethrow the exception in b(), allowing it to be seen by the caller of b(). It works exactly the same for async functions and promise .then() handlers as it does in the synchronous exception world. This was purposely designed this way to give a similar feel for promise-based async/await exception/rejections.

async function b() {
    try {
        await console.log('B');
        throw new Error('B throws Error');
    } catch(e) {
        // pseudo code for some condition that you test to determine
        // if you want to "eat" the error or let the caller see it
        if (can't continue safely) {
            // allow the exception to propagate to the caller
            throw e;    
        }
    }
}

I presume you know that async and await are for asynchronous operations which you don't actually show in your code. Nobody would do await console.log(...) in real code since that's a synchronous operation that does not return a promise so the use of await there is pointless. I'm hoping you're doing this just for the purposes of a short demo.

Upvotes: 1

Related Questions