프로미스는 JS 비동기 처리에 사용되는 객체이다. 여기서 비동기 처리란 저번 글에서 설명했던 것처럼 ‘요청을 보낸 후 응답과 관계없이 다음 동작을 실행하는 방식’이다.
프로미스는 보통 서버에서 받아온 데이터를 화면에 표시할 때 사용한다. 일반적으로 웹앱을 구현할 때 서버에서 데이터를
요청하고 받아오기 위해 실행한다.
마치 매장에서 커피를 주문했을 때 번호표를 받고 해당 순서가 되면 커피를 받으러 가는 것과 같다.
프로미스를 사용할 때 알아야 하는 기본 개념은 프로미스의 상태(state)이다. 여기서 말하는 상태는 프로미스의 처리 과정을 의미한다. new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 가진다.
Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
Fulfilled(이행=완료) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
먼저 new Promise() 메서드를 호출하면 대기 상태가 된다.
new Promise();
new promise에 전달되는 함수는 executor (실행자, 실행 함수) 라고 부른다.
new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수 인자는 resolve, reject이다.
executor에선 상황에 따라 인수로 넘겨준 콜백 중 하나를 반드시 호출해야 한다.
new Promise(( resolve, reject )=>{
// resolve(value) fulfilled
// or
// reject(“error”) rejected
});
Resolve(value) - 일이 성공적으로 끝난 경우, 그 결과를 나타내는 value와 함께 호출
reject(error) - 에러 발생 시 에러 객체를 나타내는 error와 함께 호출
여기서 콜백 함수의 인자 resolve를 아래처럼 실행하면 이행(Fulfilled) 상태가 된다.
이행 상태가 되었을 때 then()을 이용하여 처리 결과 값을 받을 수 있다.
const getEgg =() => {
return new Promise((resolve, reject) => {
let egg = 30;
resolve(egg);
});
}
//resolve()의 결과 값 egg의 갯수를 resolveEgg로 받음
getEgg().then((resolveEgg) => {
console.log(resolveEgg); //30
}) ;
new Promise()로 프로미스 객체를 생성하면 콜백 함수 인자로 resolve와 reject를 사용할 수 있다고 했는데, 여기서 reject를 아래와 같이 호출하면 실패(Rejected) 상태가 된다.
const getEgg = () => {
return new Promise((resolve, reject) =>{
reject(new Error(“not Egg”));
});
}
getEgg().then().catch((err)=> {
console.log(err);
});
프로미스의 장점은 비동기 처리시 발생하는 콜백 헬을 해결하는 것도 있지만 중요한 포인트 2가지가 있다.
비동기 처리에서는 return 값은 아무런 의미를 갖지 않는다. 함수 실행문 안에서 또 다른 함수가 실행되고 또 다른 함수가 실행되는 방식이기 때문이다. 그래서 return된 값으로 다룰 틈도 없이, 비동기 처리가 이루어진다.
하지만 프로미스를 이용할 경우, return값을 가지고 있는 프로미스 객체를 가질 수 있기 때문에 동기 코드처럼 그 값에 변수를 할당하거나, 다양한 메소드를 사용할 수 있어 자유롭게 작업이 가능하다.
비동기 처리에서 모든 콜백함수에 각각 에러 핸들링을 해줘야 했지만, 프로미스를 이용할 경우 then, catch등을 통해 에러에 대한 대처가 간결해졌다.
그러므로 프로미스의 포인트는 비동기 흐름을 동기적 흐름과 유사하게 만들어주었다는 것이다.
프로미스와 같이 비동기 모드를 작성하는 새로운 방법이며 동기적으로 처리할 수 있게 한다.
프로미스보다 코드가 간결해지고, 가독성이 높아지는 장점이 있다.
//promise
const getEgg= () => {
return new Promise((resolve, reject)=>{
const egg = 5;
resolve(egg)
});
}
// async/await
async result = () => {
const resultEgg = await getEgg();
console.log(resultEgg); // 5
}
result(); // 5
Async 함수를 실행하게 되면 프로미스 객체가 반환된다.
그러므로 async함수 내에서 return은 반환된 Promise 객체의 결과(resolve)값이다.
async egg = () => {
return 5
}
const f = egg(); // 변수 f에 프로미스 객체가 할당된다.
console.log(f) // promise { <fulfilled> : 5 }
await 는 반드시 async 안에서만 사용할 수 있고, 일반 함수에서 사용하면 에러를 발생시킨다.
JS가 await를 만나게 될 때 해당 함수가 프로미스 상태가 이행될 때까지 기다렸다가, 이행이 완료되면 그 결과 값을 반환하고 다음 코드를 실행한다.
await를 사용하면 기존의 실행 순서가 예측이 불가능했던 비동기 작동 방식이 동기적으로 실행되는 코드처럼 예측 가능해질 수 있다는 장점이 있다.
https://blog.domenic.me/youre-missing-the-point-of-promises/