일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- object detection
- 크루스칼
- back propagation
- 가끔은 말로
- lazy propagation
- DP
- 미래는_현재와_과거로
- Overfitting
- dfs
- 회고록
- 세그먼트 트리
- pytorch
- 알고리즘
- dropout
- 분할 정복
- 너비 우선 탐색
- 2023
- 가끔은_말로
- 조합론
- 백트래킹
- c++
- BFS
- tensorflow
- 우선 순위 큐
- 다익스트라
- 이분 탐색
- NEXT
- 문자열
- 플로이드 와샬
- 자바스크립트
- Today
- Total
Doby's Lab
[자바스크립트/JavaScript #5] 비동기 처리(Part 3), Promise에 대해 본문
Promise란 콜백 지옥을 가독성 있게끔 간단하게 작성하여 처리할 수 있고,
비동기 처리를 위해 자바스크립트 내부에 선언된 object이다.
Producer & Consumer
Promise는 두 가지 파트 Producer와 Consumer로 나누어 설명할 수 있다.
Producer와 Comsumer를 직관적으로 해석했을 때 이해하기 쉽다.
Producer는 예를 들어 어떤 마트가 있다고 가정한다.
Producer는 마트에 팔 물건을 다른 시장을 통해 여러 물품들을 모아서 소비자에게 제공한다.
Promise에서도 마찬가지로 서버에 접근하여 데이터를 가져오는 것처럼 이해할 수 있다.
데이터를 가져오는 것에 성공(resolve) 혹은 실패(reject)했을 때의 경우도 따져보아야 한다.
이 경우는 다음 단락에서 다루어본다.
Consumer는 마트에서 사 온 물품으로 원하는 요리를 할 수 있으며 가공할 수 있다.
Promise에서도 마찬가지로 가져온 데이터를 가지고서 원하는 형태로 가공할 수 있다.
Producer
const promise = new Promise((resolve, reject) => {
// doing some heavy work (network, read files)
console.log(`doing something...`);
setTimeout(() => {
resolve('받아온 데이터');
reject(new Error('no network'));
}, 2000);
});
Producer의 코드 형식은 다음과 같다.
자바스크립트에서 새로운 오브젝트를 선언하는 형식과 같이 new Promise();를 통해 선언하여 변수에 할당한다.
매개변수에 resolve와 reject라는 함수가 콜백 함수로 되어있는데
데이터를 받아오는 것에 성공했을 때 resolve를 통해 받아온 데이터를 할당해준다.
그와 반대로 실패했을 때는 reject를 통해 실패했을 때에 어떻게 처리할 것인지 작성한다.
Consumer
promise
.then((value) => { // resolve와 관련있음
console.log(value);
})
.catch(error => { // reject와 관련있음
console.log(error);
})
.finally(() => {
console.log(`DONE`);
});
Consumer의 코드 형식은 다음과 같다.
Promise는 선언이 되자마자 네트워크와 통신하여 데이터를 받아온다.
그러므로 Promise가 할당된 변수를 가지고서 가공을 하여 원하는 형태로 사용할 수 있다.
가공하기 위해 promise에서 제공된 기본적인 API를 알고 있어야 한다.
(바로 위 코드 블록을 기반으로 설명한다.)
.then()
resolve를 통해 받아온 데이터를 매개변수로 두고, Arrow Function을 통해 데이터를 원하는 형태로 가공하는 API
Promise는 선언되자마자 실행되어 'Doing something'이 출력되고,
받아온 데이터를 value라는 매개변수로 두고 console.log를 통해 받아온 데이터를 출력하여 .then()이 작동했음을 알 수 있다.
.catch()
자바스크립트를 통해 코드를 작성하다 보면 다음과 같은 에러를 본 적이 있을 것이다.
Uncaught Error는 Error가 발생은 했지만 어떻게 처리를 해야 하는지 선언되어있지 않을 때 발생한다.
이 경우 .catch() API에서 error로 new Error('no network')를 매개변수로 받아온 것을 어떻게 처리할 것인지 작성한다.
.catch()를 통하여 Error를 잡게 되면
위의 코드 블록에서 console.log로 error를 잡았기 때문에 console창에 Error가 뜨는 것을 확인할 수 있고,
Uncaught Error가 .catch()를 통해 해결이 되었다.
.finally()
Promise가 데이터를 받아오는 것에 성공을 했든 실패를 했든 간에 Promise 처리가 끝이 났음을 알려준다.
Promise 처리가 어찌 되었든 간에 끝이 났음을 알려주는 것을 볼 수 있다.
Chaining
Promise를 통해 비동기 처리를 하면 Call-Back 보다 더 가독성이 좋은 이유가 Chaining이다.
Chaining은 말 그대로 고리를 걸듯이 코드를 작성하는 것인데
const fetchNumber = new Promise((resolve, reject) => {
// doing some heavy work
console.log('first server 통과');
setTimeout(()=> resolve(1), 1000);
});
fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
return new Promise((resolve, reject) => {
console.log(`second server 통과`)
setTimeout(() => resolve(num - 1), 1000);
});
})
.then(num => console.log(num));
.then()을 통하여 계속 고리를 걸 듯이 데이터를 원하는 형태로 가공하여 처리를 할 수 있다.
Consumer의 코드 처리 방식에 의해 가독성이 Call-Back 보다 좋다고 할 수 있다.
3번째 .then()에서 새로운 Promise가 return이 되어 어렵게 느껴질 수 있지만
애초에 Promise에 .then()이나 .catch() API는 Promise 그 자체를 return 하기 때문에
첫 번째 Promise에서 나온 데이터가 새로운 Promise로 들어갔다고 생각하면 된다.
Call-Back To Promise
전에 포스팅했던 Call-Back 포스팅에서 콜백 지옥을 설명하기 위해 사용되었던 코드를 Promise의 형태로 바꾸어 직관적으로 코드가 간단해졌음을 확인할 수 있다.
https://draw-code-boy.tistory.com/10
[자바스크립트/JavaScript #4] 비동기 처리(Part 2), Call-Back에 대해
자바스크립트에서 비동기 처리를 시키는 방법 중 콜백에 대해 알아보자. 콜백에 대해 간단히 정의를 내려두면 매개변수(Parameter)에 함수를 할당한다. 나중에 때가 돼서 필요할 때 호출한다. 이
draw-code-boy.tistory.com
//콜백 지옥
class UserStorage{
loginUser(id, password, onSuccess, onError){
setTimeout(() => {
if(
(id === 'ellie' && password === 'dream') ||
(id === 'coder' && password === 'academy')
)
{
onSuccess(id);
}
else{
onError(new Error('not Found'));
}
}, 2000);
}
getRoles(user, onSuccess, onError){// method
setTimeout(() => {
if(user === 'ellie'){
onSuccess({name: 'ellie', role: 'admin'});
}
else{
onError(new Error('no access'));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
id,
password,
(user) =>{
userStorage.getRoles(
user,
userWithRole => {
alert(`hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
},
error => {
alert(error);
}
);
},
(error) => {console.log(error)}
);
// Promise
class UserStorage{
loginUser(id, password){
return new Promise((resolve, reject) => {
setTimeout(() => {
if(
(id === 'ellie' && password === 'dream') ||
(id === 'coder' && password === 'academy')
)
{
resolve(id);
}
else{
reject(new Error('not Found'));
}
}, 2000);
});
}
getRoles(user){
return new Promise((resolve, reject) => {
setTimeout(() => {
if(user === 'ellie'){
resolve({name: 'ellie', role: 'admin'});
}
else{
reject(new Error('no access'));
}
}, 1000);
});
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(id, password)
.then(userStorage.getRoles)
.then(user => alert(`Hello ${user.name}, you have a ${user.role}`))
.catch(alert);
콜백 지옥에서는 onSuccess와 onError 콜백을 사용하여 코드가 지저분해지고, 가독성이 떨어졌지만 Promise의 resolve와 reject가 이를 대체하면서 훨씬 가독성이 좋아졌다.
코드가 많이 길기 때문에 Consumer 코드만 따로 살펴보면 더 간단함을 알 수 있다.
// Call-Back Consumer
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
id,
password,
(user) =>{
userStorage.getRoles(
user,
userWithRole => {
alert(`hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
},
error => {
alert(error);
}
);
},
(error) => {console.log(error)}
);
// Promise Consumer
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(id, password)
.then(userStorage.getRoles)
.then(user => alert(`Hello ${user.name}, you have a ${user.role}`))
.catch(alert);
이번 포스팅에서는 비동기 처리를 할 때 Call-Back이 아닌 Promise를 사용하면 코드를 더 간단하게 나타낼 수 있음을 알 수 있었다.
다음 포스팅에서는 비동기 처리 마지막 await과 async에 대해 포스팅하겠다.