Wie wichtig es ist, Fehler in Promises immer zu erkennen
P粉590929392
P粉590929392 2024-03-19 21:05:20
0
1
404

Ich verwende @typescript-eslint/no-floating-promises Regeln in meinen Projekten. Wenn ich Code wie diesen schreibe, wird sich diese Regel beschweren -

functionReturningPromise()
    .then(retVal => doSomething(retVal));

Es will mich für diesen Promise 添加一个 catch Block. Für mich ist das sinnvoll, wenn ich dem Ausnahmebehandlungsblock Logik hinzufügen möchte. Es gibt jedoch viele Situationen, in denen ich es nicht brauche. Ich bin zufrieden mit der Fehlermeldung. Um den durch diese Regel verursachten Fehler zu unterdrücken, habe ich letztendlich Folgendes getan -

functionReturningPromise()
    .then((retVal) => doSomething(retVal))
    .catch((error) => {
        throw error;
    });
Macht es wirklich einen Unterschied, auch wenn ich das catch 块,error 仍然会以相同的方式抛出(至少在我的控制台输出中看到它)。因此,我不明白显式指定此 catch 块的意义。我错过了什么吗?如果我添加/不添加 catch 块,抛出 error wie oben nicht hinzufüge?

P粉590929392
P粉590929392

Antworte allen(1)
P粉106711425

评论者都很好地回答了您的问题 - 但为了通过示例说明为什么这很重要,请想象以下代码:

Promise.reject();
setTimeout(() => console.log('hello'), 1000);

这段代码看起来相当无害 - 有一个未处理的无操作承诺拒绝,启动后 1 秒程序将记录 'hello'

在浏览器中 - 这正是将会发生的情况 - 浏览器将记录“未捕获的承诺拒绝”错误,但否则会忽略它。

然而,在 NodeJS(从 Node v15 开始)中,未处理的 Promise 拒绝是一个硬错误 - 这意味着进程在检测到错误时将退出!

您可以通过在终端中运行代码来验证这一点(-e 的意思是“评估并运行此代码字符串”)

$ node -e "Promise.reject(); setTimeout(() => console.log('hello'), 1000)"
node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "undefined".] {
  code: 'ERR_UNHANDLED_REJECTION'
}

Node.js v18.12.1

您可以看到 'hello' 永远不会被打印,因为进程在 1 秒之前终止!

要验证事情是否按预期工作,您可以将 .reject 更改为 .resolve

$ node -e "Promise.resolve(); setTimeout(() => console.log('hello'), 1000)"
hello

因此,如果您正在使用任何 LTS 支持的版本编写 NodeJS 应用程序,那么您绝对应该处理错误,否则您将面临意外崩溃的风险。

如果您的代码仅在浏览器中运行,那么您可能想知道是否应该处理失败 - 毕竟您的用户没有查看控制台,因此他们不会知道发生了任何不好的事情,所以谁在乎呢?从“仅代码”的角度来看,您是正确的 - 但是,当出现问题时,您的用户希望从他们的应用程序中获得反馈。

想象一下以下场景 - 您的 Promise 跟踪 API 调用的结果,该调用提交用户在您的应用程序中输入的一些数据。如果该 API 调用由于某种原因失败,那么您的应用程序应该做出适当的响应并告诉用户出了问题。

处理它的替代方法可能意味着您的应用程序显示无限加载旋转器,或者用户认为他们的数据已成功提交,但实际上并未成功。无论哪种方式 - 这是一个非常糟糕且破碎的用户体验!

最后做一些像 .catch(e => { throw e }) 这样的事情,你实际上并没有处理错误。当然,这段代码会使 linter 保持沉默 - 但您所做的只是创建一个新的、被拒绝的承诺,该承诺将记录到控制台。相反,您应该以某种方式将错误连接到应用程序的 UI,例如像 .catch(e => {alert(e); throw e }) 这样简单的东西会更好。

Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage