개인사정 이슈로..^^ 오랜만에 남기는 벨로그
저번에 이어서 Promise
에 대해 복습하면서 추가 정리를 해보려한다.
유데미 강의도 좋았지만 다른 예시와 한국말로 된 강의로 이해하고 싶어서 드림코딩으로 다시 정리해봤다.
Promise 복습
동기적으로 실행되는 javascript를 비동기적으로 실행할 수 있도록 해주는 것
Callback Hell을 Promise로 간결하게 바꿔보기
예시:
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (id === 'ellie' && password === 'dream' ||
id === 'coder' && password === 'acacdemy'
) {
onSuccess(id);
} else {
onError(new Error('not Found'));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
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 => {
console.log(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 === 'acacdemy')
) {
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} role`))
.catch(console.log);
정리한 코드 해석
Promise
를 활용하였기 때문에 더이상 필요하지 않다.onSuccess
-> resolve
로, onError
-> reject
로 바꿔서 정리한다.loginUser
함수를 실행할 때는 .then
과 .catch
를 활용하여 깔끔한 코드로 바꾼다.loginUser
의 id와 password가 호출되면 // gerRoles
함수를 실행시키고 // 맞다면 경고창으로 유저의 이름과 관리자인지 아닌지를 띄운다.Async와 await
Promise 를 사용해서 깔끔해졌지만 함께 사용했을 때 더 간결하고 보기 좋게 사용할 수 있는 async
와 await
!
⭐️모든 코드를 async
와 await
로 쓴다고 좋은 것이 아니라 때마다 Promise가 필요할 때도 있고 Async와 await를 사용해야할 때도 있다는 점
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(2000);
// throw 'error'
return '🍎';
}
async function getBanana() {
await delay(1000);
return '🍌';
}
function pickFruits() {
return getApple().then(apple => {
return getBanana().then(banana => `${apple} + ${banana}`);
});
}
//사과와 바나나 함수 각각 Promise 없는 버전 (getApple 함수가 호출될 때까지 시간이 걸리게 됨)
async function pickFruits() {
const apple = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
delay
라는 함수를 활용하여 getApple()
과 getBanana()
함수를 비동기적으로 실행시킨다.
getApple()
은 사과🍎, getBanana()
는 바나나🍌 를 콘솔창에 보여준다.
위 코드에서 보면 사과와 바나나는 누가 먼저 출력이 되든 순서가 상관없는 함수이다.
이처럼 서로 관련이 없을 경우에는 병렬적 으로 실행되도록 만든다.
function pickFruits() {
const applePromise = getApple(); //만들자마자 함수 실행
const bananaPromise = getBanana(); //만들자마자 함수 실행
const apple = await applePromise;
const banana = await bananaPromise;
}
pickFruits().then(console.log);
const applePromise = getApple();
처럼 만들자마자 기다리지 않고 함수가 실행되도록 만들어준다.
하지만 실제로 이런 코드를 사용하지 않으면 유용한 Promise APIs
를 활용하는데,
바로 all, race 이다.
유용한 Promise APIs
function pickAllfruits() {
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(' + '));
}
pickAllfruits().then(console.log);
function pickOnlyOne() {
return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log);
race
: iterable 안에 있는 프로미스 중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부한다.
⭐️ 전달받은 iterable이 비어 있을 경우, 반환한 프로미스는 영원히 대기 상태
all
: 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환한다.
⭐️ 주어진 프로미스 중 하나가 거부하는 경우, 첫 번째로 거절한 프로미스의 이유를 사용해 자신도 거부
콜백지옥 함수들을 바꿔보면서 동기/비동기 활용하고 Promise가 좋을지 async,await이 좋을지 고민해봐야겠다...
Promise.. 할 수 있게찌...🥲
출처