繁体   English   中英

处理承诺中的错误的正确方法是什么?

[英]What is the proper way to handle errors in a promise?

我已经看到了几种不同的错误处理模式。

一种是这样的:

let result;

try {
    result = await forSomeResult(param);
} catch {
    throw new Error();
}

另一个是这样的:

const result = await forSomeResult(param).catch(() => throw new Error());

我更喜欢后者,因为它看起来更简洁。 但我也听说第一个解决方案更好,因为可能存在一些竞争条件,即在运行下一个命令之前.catch不执行。

我想知道是否有人有关于为什么一种方法比另一种更好的技术答案。

首先,没有理由catchthrow.catch()throw除非您要在 catch 处理程序中执行其他操作或抛出不同的错误。 如果您只想抛出相同的错误并且不执行任何其他操作,那么您可以跳过catch.catch()并将原始承诺拒绝返回给调用者。

然后,通常不建议您将await.catch()混合使用,因为代码不太容易理解。 如果您想从await捕获异常,请使用try/catch绕过它。 .catch()有效,如果您已经await承诺,它就不是首选样式。

这两种风格之间的一个技术区别

async function someFunc()
     let x = await fn().catch(err => {
         console.log(err); 
         throw err;
     });
     // do something else with x
     return something;
}

和这个:

async function someFunc()
     let x;
     try {
         x = await fn();
     } catch(err) {
         console.log(err);
         throw err;
     }
     // do something else with x
     return something;
}

是如果你调用的函数fn()同步抛出(它不应该被设计,但可能是偶然的),那么try/catch选项也将捕获该同步异常,但.catch()不会。 因为它在async函数中, async函数将捕获同步异常并将其自动转换为拒绝的承诺,以便调用者将其视为拒绝的承诺,但不会在您的.catch()记录或处理处理程序。


使用await进行try/catch更有益的情况之一是当您有多个await语句并且您不需要单独处理其中任何一个的错误时。 然后,您可以用一个try/catch它们包围起来,并在一个地方捕获所有错误。

async function someFunc(someFile) {
    let fileHandle;
    try {
        // three await statements in a row, all using same try/catch
        fileHandle = await fsp.open(someFile);
        let data = await fsp.read(...);
        // modify data
        await fsp.write(...)
    } catch(err) {
        // just log and re-throw
        console.log(err);
        throw err;
    } finally {
        // close file handle
        if (fileHandle) {
             await fileHandle.close();
        }
    }
}

这取决于

您是否要调用多个可能出错的异步函数? 您可以将它们全部包装在 try/catch 中并执行常见的错误处理,而无需重复自己:

try {
    result = await forSomeResult(param);
    await forSomeOtherResult();
    return await finalResult(result);
} catch { //catches all three at once!
    throw new Error();
}

您是否只需要处理这个特定调用的错误? .catch() 模式很好。 无需担心竞争条件, await承诺解决拒绝,这包括附加到承诺的所有成功失败回调。 但是,在您的示例中,您捕获错误只是为了抛出一个空错误 - 在这种情况下,最好简单地编写以下代码:

const result = await forSomeResult(param);

...并让错误自然地传播给调用者。

我已经看到两种风格的混合使用足够普遍,我认为无论哪种方式都很好 - 它们每个都有特定的强度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM