Promise
객체는 자바스크립트 비동기 처리에 사용되어지는 객체 되시겠다
특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 바로 실행하는 작동 방식
비동기 처리를 통해 시간이 오래걸리는 작업을 백그라운드에서 실행함으로써 성능상의 이점을 가져올 수 있다
비동기 처리는 위와 같은 장점을 가지고 있지만 서버에서 데이터를 받아와야 된다거나,
오래걸리는 작업 후 그에 대한 결과물을 보여주어야 할 때 문제가 생긴다.
예를 들어 서버로 어떠한 데이터를 보내달라는 요청을 한 이후 해당 데이터를 화면에 띄워야 할 떄,
데이터의 전송이 오래걸려 데이터가 도착하지 않았음에도 불구하고 해당 데이터를 띄우려고 하면 오류가 날 것이다.
function func(callback) {
fetch('url')
setTimeout(() => {
callback();
}, 1000);
}
function callback() {
// fetch 이후 처리할 로직
}
func((msg) => callback());
위 코드는 전통적인 방식의 setTimeout과 콜백함수를 이용하여 비동기적인 처리 흉내내는 예제이다.
...
너무... 비효율적...
Promise
Promise
는 프로미스 객체가 생성된 시점에는 알려지지 않았을 수도 있는 데이터의 현재 상태를 표현해준다.
즉, 위에 설명한 예와 같이 데이터값을 받아오는 시점에서 해당 데이터의 값을 받아는 것을 완료했는지를 Promise
를 통해 유연하게 알 수 있다는 것이다.
✅ Promise의 상태 종류
대기(Pending)
:이행하지도, 거부하지도 않은 초기 상태이행(Fulfilled)
:연산이 성공적으로 완료됨거부(Rejected)
:연산 실패‼️ then
문법을 통해 Promise
객체의 상태를 기다리고, 이 후 유연하게 로직을 처리할수 있음
‼️ 위와 같은 Promise
의 상태를 통해 아래 그림과 같이 Promise
를 통한 로직 처리
(다음 로직 이행 또는 에러, 예외 처리)
프로미스가 대기에서 벗어나 이행 또는 거부된다면 프로미스가 처리(settled)됐다고 말합니다. 프로미스와 함께 쓰이는 다른 단어인 '리졸브'(resolved)는 프로미스가 처리됐거나, 다른 프로미스의 상태에 맞춰 상태가 '잠김'됐다는 의미입니다. - MDN - Promise
또한 콜백함수를 통해 비동기처리를 하는 것 보다 then
을 이용하여 비동기 처리를 함으로써,
흔히 콜백 지옥이라고 말하는 패턴에서 벗어나 더욱 편하게 유지 보수를 할 수 있다는 것도 큰 장점이다.
async
& await
Promise
를 통해 비동기 처리 콜백 지옥에서 탈출할 수 있게 되었지만,
조금 복잡한 비동기 처리에서는 연속되는 Promise/then
도 읽기 힘든 경우가 생길 수도 있다.
(물론 이건 극단적인 경우다 ㅎ;)
async
/await
은 이를 해결하기 위해 ES2017 이후 비동기 처리 패턴을 위해 만들어진 최신 문법이다.
사용법은 간단하다.
비동기 처리를 위한 함수에 async
를 붙어 선언하고, Promise
객체를 결과값으로 반환하는 함수/메서드 앞에 await
을 붙여주기만 하면 된다.
function example() {
const phone = getData('url')
.then((data) => getUser(data)
.then((user)=> getPhone(user))
);
}
위와 같은 코드를 async
/await
을 통해 바꾸면
async function example() {
const data = await getData('url');
const user = await getUser(data);
const phone = await getPhone(user);
}
이와 같은 코드가 된다.
나만 그런지 몰라도 훨씬 읽기 쉬워진 느낌이다.
에러처리 역시 간편한데,
async function example() {
try {
const data = await getData('url');
const user = await getUser(data);
const phone = await getPhone(user);
} catch (e) {
console.log(e);
}
}
이렇게 try
/catch
문으로 예외 처리를 하면 되시겠다.