try.. catch는 finally
라는 코드 절을 하나 더 가질 수 있습니다.
*finally
안의 코드는 다음과 같은 상황에서 실행됩니다.*
*finally
를 사용하면 try..catch 를 다음과 같이 확장할 수 있습니다.*
try {
// 코드 실행..
} catch (err) {
// 에러 핸들링..
} finally {
// 항상 실행..
}
*finally
절은 무언가를 실행하고, 실행 결과에 상관없이 실행을 완료하고 싶은 경우 사용됩니다.*
피보나치 함수 fib(n) 의 연산 시간을 측정하고 싶다고 가정해 봅시다. 함수 실행 전에 측정을 시작해서 실행이 끝난 후 측정을 종료하면 되겠죠. 그런데 함수 실행 도중 에러가 발생하면 어떻게 될까요? 아래 fib(n)에는 음수나 정수가 아닌 수를 입력할 경우 에러가 발생합니다.
이런 경우에 finally를 사용할 수 있습니다. finally 절은 무슨 일이 일어났든 관계없이 연산시간 측정을 끝마치기 적절한 곳입니다. fib 함수가 에러 없이 정상적으로 실행되든 에러가 발생하든 상관없이, finally 를 사용하면 연산 시간을 제대로 측정할 수 있습니다.
let num = +prompt("양의 정수를 입력해주세요.", 35);
let diff, result;
function fib(n) {
if(n < 0 || Math.trunc(n) != n) {
throw new Error("음수나 정수가 아닌 값은 처리할 수 없습니다.");
}
return n <= 1 ? n : fib(n - 1) + fib(n - 2);
}
let start = Data.now();
try {
result = fib(num);
} catch (err) {
result = -1;
} finally {
diff = Data.now() - start;
}
alert(result || "에러 발생");
alert( `연산 시간: ${diff}ms` );
코드를 실행하고 프롬프트 대화상자에 35를 입력하면 try 다음에 finally
가 정상적으로 실행되면서 연산 시간을 확인할 수 있습니다. -1을 입력하면 에러가 발생하고, 연산 시간은 0ms가 됩니다.
*함수
는 return
이나 throw
를 만나면 종료되는데, 이렇게 finally
절을 사용하면 두 경우 모두를 처리할 수 있습니다.*
<aside>
💡 [ finally와 return ]
finally
절은 try catch 절을 빠져나가는 어떤 경우에도 실행됩니다.
return
을 사용해 명시적으로 빠져나가려는 경우도 마찬가지 입니다.
아래 예시의 try 블록 안엔 return 이 있습니다. 이 경우엔 값이 바깥 코드로 반환되기 전에 finally가 실행됩니다.
function func() {
try {
return 1;
} catch (err) {
} finally {
alert('finally');
}
}
alert( func() ); // finally 안의 alert가 실행되고 난 후, 실행됨
</aside>
<aside> 💡 [ try..finally ] catch 절이 없는 try..finally 구문도 상황에 따라 유용하게 쓸 수 있습니다. try..finally 안에선 에러를 처리하고 싶지 않지만, 시작한 프로세스가 마무리 되었는지 확실히 하고 싶은 경우에 사용합니다.
function func() {
try { // 무언가를 측정하는 경우와 같이 끝맺음이 있어야 하는 프로세스
// ..
} finally {
// 스크립트가 죽더라도 완료됨
}
}
위 코드엔 catch
가 없기 때문에 try 안에서 발생한 에러는 항상 밖으로 떨어져 나옵니다. finally
는 실행 흐름이 함수를 떠나기 전에 실행됩니다.
</aside>