“JavaScript Promise 中的 finally
在何时触发?” 这是我最近在一个研讨会上被问到的一个问题,我认为我应该写一篇小文章来消除任何困惑。
答案是,引用斯内普的话

…总是。
基本结构如下
try {
// I’ll try to execute some code for you
}
catch(error) {
// I’ll handle any errors in that process
}
finally {
// I’ll fire either way
}
例如,这个 Chuck Norris 笑话生成器的例子,其内容来自 Chuck Norris 数据库 API。(顺便说一下,我从 Todd Motto 的非常棒的开放 API 列表 中找到了这个 API,它非常适合演示和副项目。)
查看 Sarah Drasner (@sdras) 在
finally! chuck norris jokes! 中的笔。
在 CodePen 上。
async function getData() {
try {
let chuckJokes = await fetch(`https://api.chucknorris.io/jokes/random`)
.then(res => res.json())
console.log('I got some data for you!')
document.getElementById("quote").innerHTML = chuckJokes.value;
}
catch(error) {
console.warn(`We have an error here: ${error}`)
}
finally {
console.log('Finally will fire no matter what!')
}
}
在控制台

现在,让我们在 API 中引入一个错别字,并在 API 的 URL 中意外地添加一堆 r。这将导致我们的 try
语句失败,这意味着 catch
现在会抛出一个错误。
async function getData() {
try {
// let's mess this up a bit
let chuckJokes = await fetch(`https://api.chucknorrrrris.io/jokes/random`)
.then(res => res.json())
console.log('I got some data for you!')
document.getElementById("quote").innerHTML = chuckJokes.value;
}
catch(error) {
console.warn(`We have an error here: ${error}`)
}
finally {
console.log('Finally will fire no matter what!')
}
}
控制台

示例中没有说明的一个非常重要的部分是,即使在 try
或 catch
块中,return
或 break
语句停止了代码,finally
块也会运行。
何时使用它?
我发现在两种不同的情况下它特别有用,尽管我相信还有其他情况
- 当我会重复 try 和 catch 块中需要的代码时。这是我编写的一个 Vue 食谱中的示例。我在
finally
块中关闭了加载状态。这包括,就像上面的示例一样,在任何一种情况下我都需要以某种方式更改 UI。 - 当有一些清理工作要做时。Oracle 在其文档中提到了这一点。它是 Java,但前提相同。
finally
没有 try
和 catch
那么常用,但在某些用例中值得注意。希望这能澄清问题!
标题有点令人困惑。这篇文章并不是真正关于 Promise 中的 finally。这里有详细介绍:https://mdn.org.cn/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
这是关于 try/catch 中的 finally。您代码中是否有 Promise 与您是否使用
finally
无关。我也可以简单地做
根本没有 Promise。
如果您想讨论 Promise 中的 finally,您将删除 async/await 内容,并执行以下操作
async/await 只是使用 Promise 的另一种语法。
Dan,你说得对,但动态是一样的。
对于那些尚未了解或使用 async/await 的人来说,标题确实可能具有误导性。否则,只要代码是同步的,相同的原则就适用
Sarah,写得很好。我发现当代码看起来是同步的时候,解释 Promise 会容易得多,因为人们可以自上而下地阅读它并快速理解概念。
嘿,Dan!感谢你的评论。async await 运算符正在使用 Promise
https://mdn.org.cn/en-US/docs/Web/JavaScript/Reference/Operators/await
我错过了解释这一点,并使文章比它应该的更令人困惑。
感谢您提出!我以后会更注意这一点。
这就是我想到的。我同意这个评论。然而,也许我们都错过了什么……Sarah,你能详细说明一下吗?
async await 运算符确实正在使用 Promise。
但是没有必要将您示例中的代码包装在 try/catch/finally 块中。如果您在 Promise 的上下文中说明了 finally,我认为此代码是更好的示例
好文章!我可能早上没有喝咖啡,但我认为这里存在混淆,当你说
但在控制台中显示
“无论如何我都会触发”
我是一个初学者,并且容易在一些小细节上卡住。也许我错了或者遗漏了什么