关于 Promise 中 finally 的最终文章

Avatar of Sarah Drasner
Sarah Drasner

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

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

答案是,引用斯内普的话

snape saying always

…总是。

基本结构如下

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!')
  }
}

在控制台

Console that says: I got some data for you! and Finally will fire no matter what!

现在,让我们在 API 中引入一个错别字,并在 APIURL 中意外地添加一堆 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!')
  }
}

控制台

Console that has a failed GET request and then a warning that says We have an error here, Typeerror: failed to fetch, and then on a new line, Finally will fire no matter what!

示例中没有说明的一个非常重要的部分是,即使在 trycatch 块中,returnbreak 语句停止了代码,finally也会运行

何时使用它?

我发现在两种不同的情况下它特别有用,尽管我相信还有其他情况

  • 当我会重复 try 和 catch 块中需要的代码时。这是我编写的一个 Vue 食谱中的示例。我在 finally 块中关闭了加载状态。这包括,就像上面的示例一样,在任何一种情况下我都需要以某种方式更改 UI
  • 当有一些清理工作要做时。Oracle 在其文档中提到了这一点。它是 Java,但前提相同。

finally 没有 trycatch 那么常用,但在某些用例中值得注意。希望这能澄清问题!