【问题标题】:How to properly control execution flow Javascript Exception Handling如何正确控制执行流程 Javascript 异常处理
【发布时间】:2019-08-04 06:41:03
【问题描述】:

在实际代码中,我从 SQL 数据库中获取 accounts。然后,对于accounts 中的每一个account,我都会调用一些方法a()b()c()

我想要的是,如果在我调用a()b()c() 时由于任何原因发生错误(异常),则执行将停止并继续循环中的下一次迭代,即是,与下一个帐户。

所以,给定示例代码:

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()b() 将被调用,并给出以下输出:

A
B
A
B
A
B

那么,如果我在 b() 中添加一个 try/catch

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

    }
}

运行该代码时,我会得到:

A
B
C
A
B
C
A
B
C

尽管在b() 中引发了异常,但c() 也由于try/catch 被执行...

我的问题是:

如果我无法让应用程序在捕获中处于可靠状态...是 有一种方法可以让我在内部方法中继续使用 try/catch-s 但是 停止执行,所以c() 不会被执行?

ps。如果我使用异常的方式是错误的。您能帮助阐明正确的用法吗?

【问题讨论】:

    标签: javascript node.js exception


    【解决方案1】:

    如果我无法在 catch 中使应用程序处于可靠状态...有没有一种方法可以让我在内部方法中继续使用 try/catch-s 但停止执行,这样 c() 就不会被处决?

    是的,只需在b() 中重新抛出异常,让b() 的调用者可以看到它。它对async 函数和promise .then() 处理程序的工作方式与在同步异常世界中的工作方式完全相同。这是特意设计的,目的是为基于 Promise 的异步/等待异常/拒绝提供类似的感觉。

    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;    
            }
        }
    }
    

    我假设您知道asyncawait 用于异步操作,您实际上并未在代码中显示。没有人会在实际代码中使用await console.log(...),因为这是一个不返回承诺的同步操作,因此使用await 毫无意义。我希望你这样做只是为了一个简短的演示。

    【讨论】:

    • 我认为重新抛出是一种不好的做法。不是吗?也许它很常见并且可以接受...... 是的,我在控制台中使用等待,因为在实际代码中我可以使用返回承诺并在它们解决时从它们获取值的函数。
    • @Jeflopo - Rethrow 就是你的做法。这是捕获错误、检查或记录错误然后决定让它传播回调用者的适当方法。 这不是一个坏习惯。如果您需要在本地捕获它,然后让它传播回调用者,这是正确的做法。 有时,您不会在本地捕获它,而是让它始终传播。但是,如果您出于某种原因需要在本地捕获它,那么 rethrow 是决定让调用者看到它的唯一方法。这很常见。
    • 哎呀。我不确定...当你说 “传播回调用者” 在这种情况下将是 for-of 上下文,其中 b() 被调用,换句话说,父b() 在执行流程中,对吗?
    • @Jeflopo - 是的,回到调用 b() 的代码。在您的情况下,它将被main() 中的for 循环内的try/catch 块捕获,因为您使用了await b()。因此,await 将看到被拒绝的承诺从b() 返回并在本地抛出。
    猜你喜欢
    • 2017-06-25
    • 1970-01-01
    • 2010-09-10
    • 2012-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    相关资源
    最近更新 更多