Skip to main content

Блок finally

Блок finally у конструкції try...catch...finally це частина механізму обробки помилок, яка виконує код у будь-якому разі, незалежно від того, сталася помилка чи ні. Він завершує роботу конструкції: спочатку try, потім за потреби catch, і останнім завжди finally.

Теорія

TL;DR

  • finally виконується завжди, після try і після catch.
  • Він спрацює і тоді, коли в try була помилка, і тоді, коли її не було.
  • Він спрацює навіть якщо з функції вже зроблено return з блоку try або catch.
  • Він спрацює навіть якщо помилка виникла всередині самого catch.
  • Типове застосування: звільнення ресурсів і прибирання стану.
  • return усередині finally перезаписує результат функції, це погана практика.

Швидкий приклад

javascript
try { // код, який може викликати помилку } catch (error) { // обробка помилки } finally { // код, який виконається в будь-якому разі }

Як працює покроково

  1. Виконується код у блоці try.
  2. Якщо в try помилки немає, catch пропускається, виконується finally.
  3. Якщо в try виникла помилка, виконується catch, а потім finally.
  4. Після finally програма продовжує виконання далі.

Приклад 1. Помилки немає, finally все одно виконується:

javascript
try { console.log("try: усе добре"); } catch (e) { console.log("catch: помилка"); } finally { console.log("finally: виконується завжди"); }

Вивід:

text
try: усе добре finally: виконується завжди

Приклад 2. Помилка є, finally теж виконується:

javascript
try { throw new Error("Помилка!"); } catch (e) { console.log("catch:", e.message); } finally { console.log("finally: виконується завжди"); }

Вивід:

text
catch: Помилка! finally: виконується завжди

finally і return

Навіть якщо з блоку try зроблено return, блок finally усе одно виконується перед виходом з функції:

javascript
function test() { try { console.log("try"); return "З try"; } catch { console.log("catch"); } finally { console.log("finally"); } } console.log("Результат:", test());

Вивід:

text
try finally Результат: З try

Але якщо return є в самому finally, він перезаписує результат з try або catch:

javascript
function test() { try { return "З try"; } finally { return "З finally"; } } console.log(test()); // "З finally"

Це вважається поганою практикою, бо робить поведінку функції непередбачуваною: значення з try мовчки зникає.

finally при помилці в catch

finally відпрацює, навіть якщо в catch виникла нова помилка. Спочатку виконається прибирання, і лише потім помилка полетить далі вгору по стеку:

javascript
try { throw new Error("Помилка в try"); } catch (e) { console.log("catch:", e.message); throw new Error("Помилка в catch"); } finally { console.log("finally все одно виконається"); }

Вивід:

text
catch: Помилка в try finally все одно виконається Uncaught Error: Помилка в catch

Так само працює конструкція try...finally зовсім без catch: помилка не перехоплюється, але прибирання гарантовано відбувається перед тим, як вона піде далі.

Основні застосування

Звільнення ресурсів:

javascript
try { openConnection(); runQuery(); } catch (e) { console.error("Помилка:", e); } finally { closeConnection(); // виконується завжди }

Крім того, finally використовують, щоб:

  • очистити тимчасові дані й кеші;
  • зняти блокування або семафор;
  • зупинити таймер чи скасувати підписку;
  • прибрати індикатор завантаження в інтерфейсі незалежно від результату запиту;
  • завершити операцію однаково як при успіху, так і при збої.

Підсумкова таблиця

БлокКоли виконуєтьсяПризначення
tryЗавждиКод, де може статися помилка
catchЛише при помилціОбробка винятків
finallyЗавждиПрибирання, завершення, звільнення ресурсів

Типові помилки

  • return у finally. Він перекриває значення з try і catch, а також може «проковтнути» кинуту помилку, тому функція починає брехати про свій результат.
  • Ставити в finally код, який сам може впасти. Помилка в блоці прибирання перекриє початкову помилку, і справжню причину збою ви не побачите.
  • Вважати, що finally перехоплює помилку. Він не перехоплює: без catch виняток після finally летить далі вгору по стеку.
  • Дублювати прибирання і в try, і в catch, і в finally. Достатньо одного місця, саме для цього finally й існує.
  • Класти в finally бізнес-логіку. Це блок завершення, а не продовження сценарію, і читати таку функцію стає важко.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.