[JavaScript] 비동기 - then, catch, finally
1. then
- 비동기 작업이 성공적으로 완료된 후 수행할 작업을 정의하는 데 사용됩니다. then 메서드는 두 개의 콜백 합수를 매개변수로 받을 수 있습니다. 하나는 작업이 성공했을 때 호출될 함수이고, 다른 하나는 작업이 실패했을 때 호출될 함수입니다.
- onFulfilled: Promise가 이행되었을 때 호출 되는 함수입니다. 이 함수는 Promise가 반환한 값을 매개변수로 받습니다.
- onRejected: Promise가 거부되었을 때(실패했을 때) 호출되는 함수입니다. 이 함수는 오류를 매개변수로 받습니다.
promise.then(onFulfilled, onRejected);
- 사용 예제
function a() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('A');
resolve();
}, 1000);
});
}
function b() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('B');
resolve();
}, 1000);
});
}
function c() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('C');
resolve();
}, 1000);
});
}
function d() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('D');
resolve();
}, 1000);
});
}
function test() {
// 표현 방식1
a().then(() => {
b().then(() => {
c().then(() => {
d().then(() => {
console.log('Done');
});
});
});
});
// 표현 방식2
a()
.then(() => b())
.then(() => c())
.then(() => d())
.then(() => console.log('Done'));
}
test();
async - await 패턴을 적용하기 어려운 경우에 위와 같이 then으로 처리해 줄 수 있습니다. 표현 방식은 위와 같이 체이닝 방식으로도 표현할 수 있습니다. 코드의 가독성을 위해 체이닝 방식이 조금 더 권장된다고 볼 수 있습니다.
2. catch
- Promise에서 발생하는 오류를 처리하는 데 사용됩니다. 이는 then 메서드에서 전달된 콜백 함수가 실패할 때나 Promise가 거부되었을 때 호출됩니다. catch는 then메서드 체인의 끝에 추가되어 모든 종류의 오류를 한 곳에서 처리할 수 있도록 합니다.
- 사용 예제
function a(number) {
return new Promise((resolve, reject) => {
if (number > 2) {
reject();
return;
}
setTimeout(() => {
resolve();
}, 1000);
});
}
function test() {
for (let i = 1; i <= 4; i++) {
a(i)
.then(() => console.log(i, 'Resolve!'))
.catch(() => console.log(i, 'Reject!'));
}
}
test()
resolve와 reject를 인자로 하여 Promise 객체를 리턴합니다. 매개 변수로 받는 number에 따라 분기처리를 합니다. 2보다 클 때 reject 그게 아니라면 resolve를 호출합니다. test 함수에선 i를 1에서 4까지 반복하여 a 함수를 4번 호출하고 전달되는 i의 값에 따라 성공했을 때 then 구문을 실행 실패하거나 거부되었을 때 catch 구문을 실행하여 위와 같은 출력 결과를 얻을 수 있습니다.
1,2 일 때는 Promise 객체의 조건에 부합하므로 resolve를 출력합니다. 3,4 일 때는 조건에 부합하지 않으므로 reject를 출력합니다.
3. finally
- Promise에서 비동기 작업이 완료된 후에 실행되는 코드를 작성할 때 사용됩니다. finally 블록은 Promise가 성공적으로 이행되었든, 오류로 거부되었든 상관없이 항상 실행됩니다. 이를 통해 비동기 작업이 끝난 후에 반드시 수행해야 할 작업을 정의할 수 있습니다.
- 사용 예제
function a(number) {
return new Promise((resolve, reject) => {
if (number > 2) {
reject();
return;
}
setTimeout(() => {
resolve();
}, 1000);
});
}
function test() {
let str1 = '';
for (let i = 1; i <= 4; i++) {
a(i)
.then(() => (str1 = 'Resolve'))
.catch(() => (str1 = 'Reject'))
.finally(() => console.log(i, str1, 'Finished!'));
}
}
이 처럼 finally는 Promise가 성공적으로 이행(resolve) 되었든 실패나 거부(resolve) 되었든 항상 실행됨을 알 수 있습니다.
4. try... catch
- 코드 블록을 실행하고, 실행 중에 발생할 수 있는 오류를 처리하기 위해 사용됩니다. 이를 통해 오류가 발생했을 때 프로그램이 중단되지 않고 적절하게 오류를 처리할 수 있습니다. try... catch 문은 try 블록, catch 블록, 선택적으로 finally 블록으로 구성됩니다.
- 사용 예제
function a(number) {
return new Promise((resolve, reject) => {
if (number > 2) {
reject();
return;
}
setTimeout(() => {
resolve();
}, 1000);
});
}
async function test() {
try {
await a(2);
console.log('Resolve');
} catch (error) {
console.log('Reject');
} finally {
console.log('Done');
}
}
test();
try.. catch 구문을 사용하면 async await 패턴의 함수에서 Promise 속성을 사용할 수 있습니다. try 코드 블록에서 비동기로 호출된 a 함수의 실행 결과에 따라 Resolve나 Reject를 출력하고 마지막으로 finally 코드 블록을 실행합니다.
참고 문서:
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise