點燈坊

失くすものさえない今が強くなるチャンスよ

Promise 之 finally() 與 Finally

Sam Xiao's Avatar 2019-09-19

實務上有些邏輯在 Fulfilled Promise 與 Rejected Promise 都需被執行,導致 Fulfilled Handler 與 Rejected Handler 都寫了一份,此時可使用 ECMAScript 2018 的 finally()try catch finally,只需寫一份邏輯即可。

Version

macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.248
ECMAScript 2018

finally()

let fetchData = () => Promise.resolve('Hello World');

fetchData().then(
  x => {
    console.log(x);
    console.log('Fetch completed');
  }
).catch(
  e => {
    console.log(e);
    console.log('Fetched completed');
  }
);

若無論是 fulfilled promise 或 rejected promise,最後我們都希望印出 Fetched completed

若只有 then()catch(),則 fulfilled handler 與 rejected handler 都必須包含 console.log('Fetched completed')

finally000

let fetchData = () => Promise.resolve('Hello World');

fetchData()
  .then(x => console.log(x))
  .catch(e => console.log(e))
  .finally(() => console.log('Fetched completed'));

ES2018 提供了 finally(),可將 fulfilled handler 與 rejected handler 重複部分重構到 finally() 的 callback 中。

finally001

Try Catch Finally

let fetchData = () => Promise.resolve('Hello World');

try {
  let x = await fetchData();
  console.log(x);
} catch(e) {
  console.log(e);
} finally {
  console.log('Fetched completed')
}

自從 ES2017 可將 await 用於 try catch block 中之後,自然也能將 finally() 寫在 finally block 內。

這種寫法個符合 imperative 與 synchronous 習慣。

finally002

Conclusion

  • finally() 能避免 then()catch() 中有重複邏輯
  • 也可使用 try catch finally block,繼續使用 imperative 思維

Reference

Marius Schulz, Execute Cleanup Logic in a JavaScript Promise Chain with Promise.prototype.finally()
MDN, Promise.prototype.finally()