const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
});
fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
return new Promise((resolve, reject) => {
setTimeout(()=> resolve(num - 1), 1000);
});
})
.then(num => console.log(num));
then은 값을 바로 전달할 수도 있고(1,2,3), promise 객체 그 자체를 전달(4)할 수도 있다.
최종적으로 걸리는 시간은? 총 2초
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('🐓'), 1000);
});
// 닭을 받아오는 promise
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${hen} => 🥚`), 1000);
});
// 받아온 닭으로부터 달걀을 받아오는 promise
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 🍳`), 1000);
});
// 받아온 달걀로부터 요리를 만드는 promise
getHen() // 1번
.then(hen => getEgg(hen)) // 2번
.then(egg => cook(egg)) // 3번
.then(meal => console.log(meal)) // 4번
1번 - 닭을 받아온다
2번 - 닭이 받아와지면 전달받은 닭(hen)을 이용해 getEgg 호출
3번 - 그것이 수행이 되면 받아온 달걀(egg)을 가지고 cook 호출
4번 - 요리가 완료(meal)된 다음에는 그걸 출력
총 3초가 걸리겠지
코드를 조금 깔끔하게 할 수 있다.
콜백 함수를 전달할 때 받아온 값을 바로 다음에 하나로 호출하는 경우 이를 생략 가능하다.
getHen()
.then(getEgg)
.then(cook)
.then(console.log)
< 실행 결과 >
그럼 각각의 과정 도중에 Error 가 났다면 어떻게 각각을 처리해줄 것인가?
예를 들어 getEgg 에서 네트워크에 문제가 생겨 reject를 반환했다고 가정
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`error !!! ${hen} => 🥚`)), 1000);
});
// 받아온 닭으로부터 달걀을 받아오는 promise
이런 경우 각각의 구문 바로 밑에 catch로 에러를 핸들링 해주면 된다.
=> 다른 재료로 대체한다고 가정
도중 어떤 과정에 문제가 생겨도 전체적인 promise chain에 영향이 있으면 안된다.
getHen()
.then(getEgg)
.catch(error => {
return '🥖';
// getEgg에서 문제가 발생할 경우 빵을 리턴
// 아래의 과정은 그대로 진행
})
.then(cook)
.then(console.log)
< 실행 결과 >
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout( () => {
if (
(id === 'seo' && password === '4074') ||
(id === 'jiwon' && password === '8927')
) {
onSuccess(id);
} else {
onError(new Error('not found'));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout( () => {
if (user === 'seo') {
onSuccess({ name : 'seo', 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 are ${userWithRole.role}`);
},
error => {
console.log(error);
}
);
},
error => {
console.log(error);
}
);
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
setTimeout( () => {
if (
(id === 'seo' && password === '4074') ||
(id === 'jiwon' && password === '8927')
) {
resolve(id);
} else {
reject(new Error('not found'));
}
}, 2000);
};
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout( () => {
if (user === 'seo') {
onSuccess({ name : 'seo', 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)
.then(userStorage.getRoles)
// => .then(user => userStorage.getRoles(user))
// 인자가 똑같으니 생략 가능
.then(user => alert(`Hello, ${user.name}, you are ${user.role}`))
.catch(console.log);