JavaScript 공부 [10. 콜백함수를 프로미스로 바꾸기]
JavaScript는 Synchronous하다.
그 말인 즉슨 hoisting 후 순차적으로 코드를 실행한다는 뜻이다.
Hoisting: var, function 선언
Callback Hell example
- id, password를 입력해서 loginUser 함수를 실행한다.
- 로그인이 되면 onSuccess를 통해 id를 받아온다.
- 받아온 id를 이용해서 getRoles 함수를 실행한다.
- 사용자 이름이 'minbro'이면 {name: 'minbro', roll: 'admin'} 이 출력된다.
"use strict";
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => { // 로그인 하는데 2초정도 걸린다고 가정!
if(
(id === 'minbro' && password === 'minbro') ||
(id === 'test' && password === 'test')
) {
onSuccess(id)
} else {
onError(new Error('not found'))
}
}, 2000)
}
getRoles(user, onSuccess, onError) {
setTimeout(() => { // 권한 확인을 하는데 1초정도 걸린다고 가정!
if (user === 'minbro') {
onSuccess({name: 'minbro', roll: 'admin'})
} else {
onError(new Error('no access'))
}
}, 1000)
}
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your passsword");
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
Promise는 자바스크립트의 object로, 콜백함수 대신 사용할 수 있는 Asynchronous 기능이다.
State : pending -> fulfilled or rejected
Producer
const promise = new Promise((resolve, reject) => {
// doing some heavy work(network, read files)
console.log('doing something...')
})
// doing something...
// 바로 실행이 된다!
Promise는 Object를 만들면 executer가 바로 실행하기 때문에, 어떠한 이벤트로 Promise를 사용하고 싶은 경우에는 유의해야한다! (버튼을 누르면 동작한다던가...)
Consumer
then : 성공적으로 작동할 때!
catch : 에러 발생시!
finally : 성공/실패 여부와 상관없이 마지막에!
const promise = new Promise((resolve, reject) => {
// doing some heavy work(network, read files)
setTimeout(() => {
resolve("minbro");
// reject(new Error('no network'))
}, 2000);
});
promise
.then((value) => {
console.log(value);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log('finally')
})
Promise에서 성공하면 resolve 함수의 파라미터("minbro"), 실패하면 reject의 파라미터(new Error('no network'))를 리턴한다고 생각하면 쉽다!
Promise 예시
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve('chicken'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${hen} => egg`), 1000);
});
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => sunny side up`), 1000);
});
getHen()
.then(hen => getEgg(hen))
.then(egg => cook(egg))
.then(meal => console.log(meal))
// 3초 후
// chicken => egg => sunny side up
getHen()
.then(getEgg)
.then(cook)
.then(console.log)
// 인자가 하나만 있을경우 이렇게 생략해서 써도 된다고 한다!!
// 매우 놀랍다... console.log까지...?
Error Handling
위의 Promise 예시에서 에러 처리 기능을 추가해보자.
const getHen = () =>
new Promise((resolve, reject) => {
setTimeout(() => resolve("chicken"), 1000);
});
const getEgg = (hen) =>
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`error! ${hen} => egg`)), 1000);
});
const cook = (egg) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => sunny side up`), 1000);
});
getHen() //
.then(getEgg)
.catch(error => {
return 'bread'
})
.then(cook)
.then(console.log);
// 3초 후
// bread => sunny side up
.catch를 어디에 위치하느냐에 따라 에러처리가 달라지게 된다.
getHen() //
.then(getEgg)
.then(cook)
.then(console.log)
.catch(console.log);
// 3초 후
// Error: error! chicken => egg
// getEgg 에서 발생한 에러를 계속 넘겨주다가 마지막 catch에서 로그로 출력한다.
이제 에러처리를 배웠으니, 앞서 작성했던 Callback Hell Example 코드를 Promise를 사용하여 수정해보자
"use strict";
class UserStorage {
loginUser(id, password) { // onSuccess, onError 파라미터를 쓰지 않는다!!!
return new Promise((resolve, reject) => { // 대신 Promise를 사용!!!
setTimeout(() => {
if (
(id === "minbro" && password === "minbro") ||
(id === "test" && password === "test")
) {
resolve(id); // onSuccess 대체!!
} else {
reject(new Error("not found")); // onError 대체!!!
}
}, 2000);
});
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === "minbro") {
resolve({ name: "minbro", role: "admin" });
} else {
reject(new Error("no access"));
}
}, 1000);
});
}
}
const userStorage = new UserStorage();
const id = prompt("enter your id");
const password = prompt("enter your passsword");
userStorage
.loginUser(id, password)
.then(userStorage.getRoles)
.then((user) => alert(`Hello ${user.name}, you have a ${user.role} role`))
.catch(console.log);
// 코드가 훨씬 간결해지고 알아보기도 쉽다!
Author And Source
이 문제에 관하여(JavaScript 공부 [10. 콜백함수를 프로미스로 바꾸기]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@minbrother/JavaScript-공부-10저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)