비동기 처리는 앞선 작업이 끝난 후 다음 작업이 실행되는 동기와 달리, 앞선 작업의 완료 여부와 관계 없이 후에 이어지는 작업을 하는 방식입니다.
왜 작업을 순서대로 처리하지 않느냐 ? 라고 물으신다면, 작업을 한 개씩 처리하는 방식은, 업무는 단순할 수 있으나 자원이 비효율적으로 사용되기 때문입니다.
예를 들어, 일상에서 어떠한 프로그램을 다운하는 데 10분이 걸린다고 생각해봅시다. 우리는 자연스레 프로그램이 다운로드 되는 동안 다른 할 일을 할텐데요, 이것이 바로 비동기 처리입니다. 프로그램이 다운로드 되는 시간동안 우리는 동시에 다른 일을 하고 있으니까요 !
10분이 걸리는 다운로드를 동기적으로 처리한다면, 우리는 다운로드가 완료될 때까지 아무것도 못하고 하염없이 기다리게 될 것입니다. 비효율적이죠 ?
따라서, 웹 상에서 파일을 받아오거나, 데이터베이스 처리를 하는 등 시간이 상대적으로 오래 걸리는 작업을 할 때에는 비동기 처리를 할 수 있도록 하여, 오랜 시간 작업이 진행되는동안 다른 일을 할 수 있도록 합니다.
위의 글을 읽어보면 그러면 동기는 왜 있나요 ? 할 수 있지만, 동기적 처리도 꼭 필요한 경우가 있습니다. A 작업의 결과인 a 정보를 사용하여 B에서 작업을 처리한다고 가정한다면, A 작업이 완료되지 않은 채 B 작업을 시작할 시 우리는 올바른 작업을 진행할 수 없겠죠 ?
따라서 우리는 상황에 따라 동기와 비동기를 적절히 사용할 줄 알아야합니다.
콜백 함수를 사용하지 않고 비동기 처리를 하기 위해 JS에서 제공하는 object로, 성공과 오류에 대한 응답 처리로 이루어져 있습니다
우리는 promise를 사용할 때 , .then
, .catch
를 사용한다는 것을 세미나 때 배웠습니다. + finally
까지 해서 조금 더 자세히 알아봅시다.
.then
: 비동기 처리가 성공할 경우, resolve 내의 값을 받아온다.catch
: 비동기 처리가 실패하였을 때, reject 내의 값을 받아온다.finally
: 비동기 처리의 성공 여부와 관계 없이 실행하고자 하는 기능을 넣어준다const promise = new Promise((resolve, reject) => {
if (condition) {
resolve("비동기 처리 성공");
} else {
reject("비동기 처리 실패");
}
});
//* 비동기 처리 성공(then), 비동기 처리 실패(catch)
promise
.then((resolvedData): void => console.log(resolvedData))
.catch((error): void => console.log(error));
.finally(() => {console.log("finally")})
자 위와 같은 코드가 있다고 가정해봅시다. 각각 condition이 true
/false
일 때의 실행 결과는 아래와 같습니다.
비동기 처리의 성공 여부와 관계 없이 finally
안의 코드가 실행되는 것을 확인할 수 있죠 !
정답은 NO 입니다.
promise
.then()
.then()
.then()
위와 같은 promise chaining 코드에서 에러는 어디에서 발생할 지 모르죠.
이러한 경우 그러한 에러를 잡기 위해 모든 .then
다음에 .catch
를 적어주어야하냐 ? 하면 아닙니다!
catch
는 한 번의 사용으로 연결된 모든 promise에 대한 reject를 해결합니다.
따라서, 아래와 같이 한 번만 적어주셔도 괜찮습니다.
promise
.then()
.then()
.then()
.catch() // 이렇게 한 번만 써줘도 된다 !!
우리는 위에서 reject 내에 error 시 반환할 문자열을 넣고, console.log
를 해주었습니다. (세미나 코드에서는 reject 내에 new Error(문자열)
형태로 되어있죠 !)
그러나, error을 console.log
를 통해 출력해주는 것은 좋은 방식이 아닙니다.
다음 세 개의 문서에서 제가 소개할 내용에 대해 보다 자세한 내용을 다루고 있으니 참고 부탁드립니다. (전 아주 간략 of 간략으로 소개드릴 것 ,,)
짜잔,,
promise
.then((resolvedData): void => console.log(resolvedData))
.catch((error): void => {throw new Error(error)})
.finally(() => {console.log("finally")});
.catch
내의 (error)은 우리가 reject 내에 적어준 문자열일 것이며, 우리는 이를 Error 객체로 묶어 throw로 던져줍니다 !
throw는 의도적으로 에러를 직접 발생시키는 것이에요
세미나 때의 코드를 그대로 실행시킨다면 아래와 같이 Error가 보일텐데요,
위의 코드를 실행시키면 아래와 같이 뜹니다. 에러가 발생한 줄이 다르죠 ?? 위 결과에서 나타내는 11번째 줄은 reject(new Error(”~~”))
가 있는 줄, 아래 결과의 18번째 줄은 .catch((error): void => {throw new Error(error)})
가 있는 줄입니다 !
그렇다면 세미나 코드에서 조금 더 깔끔하게 Error을 출력하는 방법이 없을까 ! 한다면 error.name
과 error.message
에 대해 알고 계셔야 하는데요,
Error : 비동기 처리 실패 에서 Error
는 error.name
, 비동기 처리 실패 는 error.message
에 해당합니다.
.catch((error): void => console.log(error.name,':',error.message))
따라서 위와 같이, error.name
과 error.message
만을 출력하게 해준다면 아래와 같이 깔꼼하게 볼 수 있습니다 !