자바스크립트의 Promise문법은 Callback Function의 단점을 보완하고자 ECMAScript 2015에 추가된 문법입니다.
콜백 함수의 단점은 대표적으로 콜백 지옥이 있습니다.
콜백 지옥은 콜백 함수는 비동기에 사용되는데 함수 내부에 콜백함수를 동기적으로 실행되게끔 코드를 작성하기 때문에 생기는 문제입니다.
아래와 같이 말이죠.
step1(function (value1) {
step2(function (value2) {
step3(function (value3) {
step4(function (value4) {
step5(function (value5) {
// 탈출
});
});
});
});
});
위와 같이 단순한 형태를 가진 함수가 겨우 5번 정도 중첩됬을 뿐인데, 잘 이해가 되질 않고 또 가독성도 매우 떨어집니다.
이런 문제를 해결하기 위해서 나온 문법이 Promise입니다.
MDN에 나온 Promise 객체에 대한 설명을 좀 이해하기 쉽게 바꿔서 표현하면 다음과 같습니다.
Promise 객체는 비동기 처리가 끝나는 시점에 작업의 완료 또는 실패에 대한 결과 값을 나타냅니다.
Promise의 상태는 3가지로 나뉩니다.
Pending : 비동기 처리에 대한 작업이 진행 중
Fullfilled : 비동기 처리가 성공적으로 완료
Rejected : 비동기 처리에 문제가 생겨 실패
<HTML>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="module" src="promise.js"></script>
<title>Promise</title>
</head>
<body>
</body>
</html>
<Javascript>
// 이전에 콜백함수에 대해서 설명할 때 사용한 예제
const setTimeoutWithAnimationFrame = (callback, time) => {
let start = new Date().getTime();
const fn = () => {
let ts = new Date().getTime();
if (ts - time > start) {
callback();
} else {
requestAnimationFrame(fn);
}
};
requestAnimationFrame(fn);
};
const getUser = () => {
// Promise가 생성되는 부분이 Pending에 해당
return new Promise((resolve, reject) => {
const user = {
id: 1,
name: 'jade',
age: 10,
};
// 네트워크 통신을 하는 함수라고 가정
setTimeoutWithAnimationFrame(() => {
if (Math.random() <= 0.5) {
// 성공적으로 데이터를 가져왔으므로 Fullfilled에 해당하는 함수 호출
resolve(user);
} else {
// 데이터를 가져오는데 실패했으므로 Rejected에 해당하는 함수 호출
reject(new Error('사용자의 데이터를 가져오는데 실패 했습니다.'));
}
}, 1000);
});
};
getUser()
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
getUser 함수의 선언 부분을 보면 Promise 객체를 생성할 때 매개변수가 resolve, reject인 콜백함수를 넘겨줍니다.
(여기서 매개변수인 resolve, reject가 어떻게 넘어오는지 감이 잡히지 않으시는 분들은 다시 콜백함수에 대해서 공부하시면 됩니다.)
이 때 생성된 Promise 객체는 Pending 상태로 들어가게 되고 1초뒤에 일정확률로 성공, 실패가 결정되는 함수가 실행됩니다.
사용자의 데이터를 가져오는 것이 성공했다면 resolve 함수에 user객체를 넘겨주고, 실패했다면 reject 함수를 호출할 때 에러를 던져줍니다.
getUser 함수의 호출을 진행한 뒤에 then 함수가 호출됩니다. 이 then함수는 Promise 객체가 가지고 있는 기본 함수입니다. 첫 번째 매개변수로 넘겨주는 콜백함수 내에서 return 예약어를 사용해서 어떠한 처리를 진행한 후에 다음 then 함수로 넘겨줄 수 있습니다.
예를 들면 다음과 같이 가능합니다.
getUser()
.then((user) => {
console.log(user);
user.id = 12;
return user;
})
.then((user1) => {
console.log(user1);
});
그러니까 then함수는 다른 Promise 객체를 반환하는 기능과 이전 Promise 객체에서 완료된 결과를 가져와서 처리도 해주는 두 가지 기능을 가진 함수라고 생각할 수 있습니다.
그리고 then함수에서 에러 처리도 가능은 하지만 자주 사용하지는 않으므로 다른 방법을 사용한 에러 처리에 대해서 설명하겠습니다.
맨 위의 예제에서 다음과 같은 형태의 함수호출이 있었습니다.
getUser()
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
getUser 함수를 호출한 뒤에 내부의 Promise 객체에서 reject 함수가 호출됬다면 위의 then 함수를 무시하고 바로 catch 함수가 실행되는 것을 알 수 있습니다.
참고
https://yoonucho.github.io/review/2019/01/31/callback_function.html
https://ko.javascript.info/promise-basics
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
'취업 > 기록' 카테고리의 다른 글
D - Day 93 - 2 (자바스크립트 async, await 문법) (0) | 2021.06.15 |
---|---|
D - Day 93 - 1 (함수에 대한 기본) (0) | 2021.06.15 |
D - Day 97 (자바스크립트 Callback Function) (0) | 2021.06.11 |
D - Day 98 (Event Delegation) (0) | 2021.06.10 |
D - Day 100 (0) | 2021.06.08 |