翻譯練習html
原博客地址:Will it finally: a try/catch quiznode
你知道
try
和catch
是怎麼工做的,可是你知道finally
是怎麼工做的嗎?它是在拋出異常後執行仍是在return
語句後執行?async
隨着async/await
的出現,我發現我最近在個人代碼裏try/catch/finally
用的愈來愈多。可是老實說,我對finally
有一些陌生。當我實際去使用它的時候,我對它的具體細節有一點不肯定。因此我舉例幾個例子。編輯器
考慮在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
塊內拋出的。網站
你知道若是你提供了一個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?
因此,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的代碼。事實上,這就是這篇文章的靈感來源。
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/finally
在JavaScript
中的async/await
新語法中也能完美運行。因此這也提醒你去溫習一下async/await
,如今,是時候去逛逛個人Mastering Asynchronous JavaScript 課程了。