JS Promise 에 대해 간단 이해해보기
목적
아무리 해봐도, Promise
가 뭔지 잘 모르겠었어서 일단 차근차근 정리해보기 위해 간단한 내용부터 시작해 살을 붙여보려고 한다.
Promise 란?
1
2
✨ JS 에서 비동기 작업의 최종 완료 또는 실패를 나타내는 객체.
비동기 작업이 수행이 될 때, 그 결과를 보장해주는 역할(성공, 실패 무관)
그래서, Promise 는 비동기 작업의 상태를 3가지로 표현한다.
- Pending(대기중) : 요청을 보낸 후, 아직 결과가 정해지지 않은 상태
- Fulfilled(성공) : 응답을 성공적으로 받아 Promise 가 결과를 return.
- Rejected(거부됨) : 오류 또는 실패로 인해 응답을 받지 못한 상태
사용법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Promise : JS 에서 비동기 작업의 최종 완료, 실패를 나타내는 객체
// ==> 비동기 작업의 결과를 반드시 보장함(성공, 실패 무관)
const promise = new Promise((resolve, reject) => {
if (true) resolve("1");
else reject("0");
});
// 비동기 요청이 성공하면 then() 이 동작, 실패하면 catch() 가 동작함.
// 그때 resolve() 로 넘겨진 값은 then() 으로, reject() 로 넘겨진 값은 catch() 로.
promise
.then((value) => {
/* 성공시 실행할 콜백 함수 */
console.log("then : " + value); // "then : 1
})
.catch((err) => {
/* 실패시 실행할 콜백 함수 */
console.log("catch : " + err);
})
.finally((value) => {
// 요청 결과와 무관하게 무조건 실행되는 콜백함수
console.log("finanlly : " + value);
}); // "finally : undefined"
위 예시에서 myPromise
함수를 선언할 때, 요청이 성공했을 때와 실패했을 때로 나누어 처리를 할 수 있다.
요청이 성공했을 때는, resolve()
가 호출되어 값이 전달 된다. 이후, then()
을 통해 값을 전달받아 콜백함수를 실행한다. 반대로 실패했을 땐, reject()
가 호출된다. catch()
를 통해 값을 전달 받고 콜백함수를 실행한다. finally()
는 promise 의 결과와 관계 없이 무조건 실행이 되는 코드다.
위 3가지는 promise handler 라고 부른다. 프로미스 핸들러 또한, 프로미스 객체를 반환하기 때문에 handler chaining 이 가능해진다. 이 때문에, 프로미스 지옥에 빠지게 되기도 한다..
fetch()
에 대해
Promise 에 대해 찾아보게 된다면 fetch()
라는 메서드는 이미 접했을 것이다. fetch()
는 스스로 프로미스 객체를 생성해 이를 반환해주는 역할을 한다.
1
2
3
4
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json()) // 응답 객체에서 JSON 데이터를 추출한다.
.then((data) => console.log(data)); // JSON 데이터를 콘솔에 출력한다.
.catch((err) => console.log(err)); // 실패시 에러 처리
따라서, fetch()
또한 promise 와 동일하게 사용하면 된다.
Promise Hell
Promise 에서 사용할 수 있는 다양한 정적 메서드가 있지만, 여기서는 넘어가겠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fetch("https://api.github.com/users")
.then((response) => {
if (response.ok) {
return response.json();
} else {
throw new Error("Network Error");
}
})
.then((users) => {
return users.map((user) => user.login);
})
.then((logins) => {
return logins.join(", ");
})
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
위는 참조링크, 인파님 블로그 에서 가져온 예시 코드다.
위 코드는 API 호출을 진행해, 가져온 정보를 .then()
메서드로 여러번 연결해 문자열로 표현하는 동작을 수행한다.
이렇게 메서드가 연속되다보면, 결국 새로운 지옥이 열리게 된다..
이를 개선하려면 아래처럼 async
/ await
를 사용하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
try {
const response = await fetch("");
if (response.ok) {
const users = await response.json();
const logins = users.map((user) => user.login);
const result = logins.join(", ");
console.log(result);
} else {
throw new Error("Network Error");
}
} catch (error) {
console.error(error);
}
async
/ await
에 대해서는 다른 포스팅으로 자세히 다뤄보자.