finally會執行嗎:try/catch的測試

翻譯練習html

原博客地址:Will it finally: a try/catch quiznode

你知道trycatch是怎麼工做的,可是你知道finally是怎麼工做的嗎?它是在拋出異常後執行仍是在return語句後執行?async

隨着async/await的出現,我發現我最近在個人代碼裏try/catch/finally用的愈來愈多。可是老實說,我對finally有一些陌生。當我實際去使用它的時候,我對它的具體細節有一點不肯定。因此我舉例幾個例子。編輯器

當你拋出一個catch

考慮在catch中拋出一個異常這種狀況。在你退出函數以前沒有東西去捕獲拋出的異常。這個時候,finally會執行嗎?爲了找到答案,在編輯器的底部取消example()調用的註釋!函數

function example() {
  try {
    fail()
  }
  catch (e) {
    console.log("Will finally run?")
    throw e
  }
  finally {
    console.log("FINALLY RUNS!")
  }
  console.log("This shouldn't be called eh?")
}

// example()

Result:工具

Will finally run?
FINALLY RUNS!
errorReferenceError: fail is not defined
    at fail (index.js:3:4)
    at example (index.js:15:0)
    at e.execute (https://frontarm.com/8058525ee5952d818c1c0e294c9d4365.js:1:29826)
    at handleUnrequiredPrepared (https://frontarm.com/8058525ee5952d818c1c0e294c9d4365.js:1:26656)

finally運行了,儘管最後一個log語句沒有運行!你能夠看到finally有一點特殊;它容許你在拋出一個錯誤和離開函數以前運行,儘管這個錯誤是在一個catch塊內拋出的。網站

沒有catch試試

你知道若是你提供了一個finally塊,你能夠不提供catch塊嗎?你可能知道,但這值得一問!ui

因此下一個問題:即便在try塊中沒有發生錯誤,finally塊會執行嗎?若是你不肯定,取消編輯器的最後一行代碼來找出答案。翻譯

function example() {
  try {
    console.log("Hakuna matata")
  }
  finally {
    console.log("What a wonderful phrase!")
  }
}

// example()
Hakuna matata
What a wonderful phrase!

是的,儘管沒有任何錯誤,finally仍是執行了。固然,在錯誤發生的時候它也會執行。這就是finally的目的--它容許你處理這兩種狀況,就像你在下面的例子中看到的:code

function example() {
  try {
    console.log("I shall try and fail");
    fail();
  }
  catch (e) {
    console.log("Then be caught");
  }
  finally {
    console.log("And finally something?");
  }
}

// example()
I shall try and fail
Then be caught
And finally something?

Return 和 finally

因此,finally容許你在錯誤發生後進行一些清理。可是,若是沒有任何錯誤發生,僅僅是函數的在try塊中的一個正常的return語句會怎樣呢?

看看下面的例子。當你已經執行過return語句,example() 函數中的finally塊還會執行嗎?在編輯器底部取消example()的註釋而後找出答案。

function example() {
  try {
    console.log("I'm picking up my ball and going home.")
    return
  }
  finally {
    console.log('Finally?')
  }
}

// example()
I'm picking up my ball and going home.
Finally?

規則

try/catch/finally中,finally塊總會執行--哪怕提早執行到return語句或者拋出異常。
這就是它爲何這麼有用。這是編寫那些無論怎樣都要運行的代碼的完美場所,像是處理異常I/O的代碼。事實上,這就是這篇文章的靈感來源。

我用finally幹什麼

Frontend Armory是一個靜態渲染的網站,它是經過一個叫Navi的工具構建的,它容許你配置一個renderPageToString()函數,這個函數用來渲染每一個頁面。

爲了確認renderPageToString()函數的每次調用都獨立於上一次的調用,Navi用try/catch/finally 和一些obscure node-fu來卸載那些在渲染過程當中加載的模組。

let oldCacheKeys = new Set(Object.keys(require.cache))
try {
  html = await renderPageToString(options)
}
catch (e) {
  throw e
}
finally {
  process.env.NODE_ENV = nodeEnv

  for (let key of Object.keys(require.cache)) {
    if (!oldCacheKeys.has(key)) {
      delete require.cache[key]
    }
  }
}

從上面的例子能夠看出,try/catch/finallyJavaScript中的async/await新語法中也能完美運行。因此這也提醒你去溫習一下async/await,如今,是時候去逛逛個人Mastering Asynchronous JavaScript 課程了。

相關文章
相關標籤/搜索