3-8. Promise(콜백 지옥에서 우리를 구원하다)
2022. 6. 21. 23:53ㆍReact/한입 크기로 잘라 먹는 리액트(React.js)
비동기 작업이 가질 수 있는 3가지 상태
function isPositive(number, resolve, reject) {
setTimeout(() => {
if (typeof number === "number") {
// 성공 -> resolve
resolve(number >= 0 ? "양수" : "음수");
} else {
// 실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다.");
}
}, 2000);
}
isPositive(
2,
(res) => {
console.log("성공적으로 수행 됨 : ", res);
},
(err) => {
console.log("실패 하였음 : ", err);
}
);
이렇게 callback함수를 통해 비동기처리로 성공 및 실패를 내보았다.
Promise를 통해서 비동기 처리를 해보자
function isPositive(number, resolve, reject) {
setTimeout(() => {
if (typeof number === "number") {
// 성공 -> resolve
resolve(number >= 0 ? "양수" : "음수");
} else {
// 실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다.");
}
}, 2000);
}
function isPositiveP(number) {
const executor = (resolve, reject) => {
// 실행자
setTimeout(() => {
if (typeof number === "number") {
// 성공 -> resolve
console.log(number);
resolve(number >= 0 ? "양수" : "음수");
} else {
// 실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다.");
}
}, 2000);
};
const asyncTask = new Promise(executor);
return asyncTask;
}
isPositiveP(101);
// isPositive(
// 2,
// (res) => {
// console.log("성공적으로 수행 됨 : ", res);
// },
// (err) => {
// console.log("실패 하였음 : ", err);
// }
// );
여기서 isPositiveP의 반환 함수는 Promise인것을 확인할 수 있다.
Promise를 반환한다는 것은, 이 함수가 비동기 작업을 하고 작업의 결과를 Promise 객체로 반환받아서 사용할수 있는 함수
Promise의 비동기 처리의 결과값을 사용하는 방법
function isPositive(number, resolve, reject) {
setTimeout(() => {
if (typeof number === "number") {
// 성공 -> resolve
resolve(number >= 0 ? "양수" : "음수");
} else {
// 실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다.");
}
}, 2000);
}
function isPositiveP(number) {
// executor는 실행자로, 비동기 함수를 실행하는 것
const executor = (resolve, reject) => {
setTimeout(() => {
if (typeof number === "number") {
// 성공 -> resolve
console.log(number);
resolve(number >= 0 ? "양수" : "음수");
} else {
// 실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다.");
}
}, 2000);
};
// 실행시키는 방법
// new로 promise 객체를 생성함으로 exector를 넘겨주면 바로 수행 됨
const asyncTask = new Promise(executor);
// 그래서 반환 값이 Promise가 된다.
// Promise 반환 함수 - 비동기 작업을 하고, 작업의 결과를 Promise 객체로 받아서 이용할 수 있음
return asyncTask;
}
const res = isPositiveP(101);
res
.then((res) => {
console.log("작업 성공 : ", res);
})
.catch((err) => {
console.log("작업 실패 : ", err);
});
// isPositive(
// 2,
// (res) => {
// console.log("성공적으로 수행 됨 : ", res);
// },
// (err) => {
// console.log("실패 하였음 : ", err);
// }
// );
Promise를 통해 Callback 지옥을 벗어나보자.
아래는 콜백 지옥 함수
function taskA(a, b, cb) {
setTimeout(() => {
const res = a + b;
cb(res);
}, 3000);
}
function taskB(a, cb) {
setTimeout(() => {
const res = a * 2;
cb(res);
}, 3000);
}
function taskC(a, cb) {
setTimeout(() => {
const res = a * -1;
cb(res);
}, 3000);
}
taskA(3, 4, (a_res) => {
console.log("task A : ", a_res);
taskB(a_res, (b_res) => {
console.log("task B : ", b_res);
taskC(b_res, (c_res) => {
console.log("task C : ", c_res);
});
});
});
아래와 같이 이렇게 만들었는데 또 콜백 헬이 나타났다.
function taskA(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a + b;
resolve(res);
}, 3000);
});
}
function taskB(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * 2;
resolve(res);
}, 3000);
});
}
function taskC(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * -1;
resolve(res);
}, 3000);
});
}
taskA(5, 1).then((a_res) => {
console.log("A RESULT : ", a_res);
taskB(a_res).then((b_res) => {
console.log("B RESULT : ", b_res);
taskC(b_res).then((c_res) => {
console.log("C RESULT : ", c_res);
});
});
});
--> then을 이렇게 사용하는것이 아니어서 그렇다.
그래서 아래와 같이 넣을 수 있는데
function taskA(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a + b;
resolve(res);
}, 3000);
});
}
function taskB(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * 2;
resolve(res);
}, 3000);
});
}
function taskC(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * -1;
resolve(res);
}, 3000);
});
}
// then chaining
taskA(5, 1)
.then((a_res) => {
console.log("A RESULT : ", a_res);
return taskB(a_res);
})
.then((b_res) => {
console.log("B RESULT : ", b_res);
return taskC(b_res);
})
.then((c_res) => {
console.log("C RESULT : ", c_res);
});
// callback hell
// taskA(5, 1).then((a_res) => {
// console.log("A RESULT : ", a_res);
// taskB(a_res).then((b_res) => {
// console.log("B RESULT : ", b_res);
// taskC(b_res).then((c_res) => {
// console.log("C RESULT : ", c_res);
// });
// });
// });
then method들을 이어서 사용할 수 있다.
이를 then chaining이라고 한다.
then chaining은 중간에 뚝 끊을 수 있는데, callback hell인 구문은 계속 이어져서 해야하기 때문에 then chaining이 좋음
function taskA(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a + b;
resolve(res);
}, 3000);
});
}
function taskB(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * 2;
resolve(res);
}, 3000);
});
}
function taskC(a) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = a * -1;
resolve(res);
}, 3000);
});
}
// then chaining
const bPromiseResult = taskA(5, 1).then((a_res) => {
console.log("A RESULT : ", a_res);
return taskB(a_res);
});
console.log("this is the blank");
bPromiseResult
.then((b_res) => {
console.log("B RESULT : ", b_res);
return taskC(b_res);
})
.then((c_res) => {
console.log("C RESULT : ", c_res);
});
// callback hell
// taskA(5, 1).then((a_res) => {
// console.log("A RESULT : ", a_res);
// taskB(a_res).then((b_res) => {
// console.log("B RESULT : ", b_res);
// taskC(b_res).then((c_res) => {
// console.log("C RESULT : ", c_res);
// });
// });
// });
so, 가독성 있고 깔끔한 비동기 처리를 할 수 있게 된다.
'React > 한입 크기로 잘라 먹는 리액트(React.js)' 카테고리의 다른 글
3-10. API & fetch (Promise/async&await/fetch/API) (0) | 2022.06.28 |
---|---|
async & await - 직관적인 비동기 처리 코드 자성 (0) | 2022.06.27 |
3-7. 동기 & 비동기 (순서대로 실행하는 것과 그렇지 않은 것 들) (0) | 2022.06.21 |
3-6. spread 연산자(배열과 객체를 한줄로 펼치는 방법) (0) | 2022.06.21 |
3-5. 비 구조화 할당(배열과 객체를 우아하게 사용하는 방법) (0) | 2022.06.21 |