JavaScript & Node.js
#.13 비동기 [Promise]
Haksae
2022. 1. 9. 15:44
* Promise
- promise : JS에서 제공하는 비동기를 간편하게 처리할 수 있는 object
- 비동기적인 것을 수행할 때 콜백함수 대신에 유용하게 쓸 수 있는 오브젝트
- 정해진 장시간의 기능을 수행하고나서 정상적으로 기능이 수행되어졌다면 성공의 메시지와 함꼐 처리된 결과 값을 전달, 기능을 수행하다가 문제가 발생했다면 에러를 전달해줌
* promise 중요포인트 2가지
1. State
- 기능 수행이 성공했는지 실패했는지 이런 상태에 대한 이해 중요
2. Producing vs Consumer
- producing : 우리가 원하는 데이터를 제공하는 사람
- consumer : 데이터를 필요로 하는 사람
1. Producer
- promise를 만드는 순간 executor라는 콜백 함수가 바로 실행됨
- 유의 : 사용자가 요구하지 않은 불필요한 네트워크 통신이 발생할 수 있음
- resolve() : 기능을 성공적으로 수행되었을 때 호출
'use strict';
// Promise is a JavaScript object for asynchronous operation.
// State: pending -> fulfilled or rejected
// Producer vs Consumer
// 1.Producer
// when new Promise is crated, the executor runs automatically
const promise = new Promise((resolve, reject)=>{
// doing some heavy work (network, read files)
console.log('doing something...');
setTimeout(()=>{
resolve('haksae'); // 콜백함수를 통해 전달
}, 2000);
});
- 예시 : 서버에서 어떤 일을 하다가 잘 마무리하고, resolve라는 함수를 통해 값 전달
2. Consumers : then, catch, finally
- then()
- Promise가 정상적으로 수행이 되어서 resolve콜백 함수를 통해 전달한 값이 then(value)의 파라미터로 전달이 되어져서 들어옴
- then은 promise도 전달이 가능하다.
promise.then((value) => {
console.log(value);
});
- reject(), catch()
- reject : 기능 수행에 에러가 발생되었을 때 호출
- 에러 오브젝트에는 에러 이유를 잘 명시해야함
- catch()
- promise가 기능 수행에 에러가 발생하여 reject 콜백 함수를 통해 전달한 값이 catch(eooro)의 파라미터로 전달되어서 들어옴
const promise = new Promise((resolve, reject)=>{
console.log('doing something...');
setTimeout(()=>{
// resolve('haksae');
reject(new Error('no network'));
}, 2000);
});
// Consumers: then, catch, finally
promise
.then(value =>{
console.log(value);
})
.catch(error =>{
console.log(error);
});
- finally()
- 성공과 실패와 상관 없이 무조건 마지막에 호출되어지는 함수
.finally(()=>{
console.log('finally');
});
3. Promise chaining
- then을 여러가지 비동기적인 함수도 같이 묶어서 처리할 수 있음
→ then은 값을 바로 전달할 수도 있고 Promise를 전달할 수도 있다.
const fetchNumber = new Promise((resolve, reject)=>{
setTimeout(() => resolve(1), 1000);
});
// 비동기인 함수도 묶어서 처리
fetchNumber
.then(num => num*2) // 2
.then(num => num*3) // 6
.then(num => {
return new Promise((resolve, reject)=>{
setTimeout(() => resolve(num-1), 1000); // 5
});
})
.then(num => console.log(num));
const getHen = () =>
new Promise((resolve, reject)=> {
setTimeout(() => resolve('🐔'), 1000);
});
const getEgg = hen =>
new Promise((resolve, reject)=> {
setTimeout(() => resolve(`${hen} => 🥚`), 1000);
});
const cook = egg =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 🍳`), 1000);
});
/*
getHen()
.then(hen => getEgg(hen))
.then(egg => cook(egg))
.then(meal => console.log(meal));
*/
getHen()
.then(getEgg)
.then(cook)
.then(console.log);
4. Error Handling
- 만약 위의 프로미스에서 실패시 아래와 같은 에러가 발생한다.
- 에러를 핸들링 하기 위해서 catch() 를 써야한다.
getHen()
.then(getEgg)
.then(cook)
.then(console.log)
.catch(console.log);
- 에러가 발생하여도 중단되지 않고 대체방안으로 작동시키는 방법
getHen()
.then(getEgg)
.catch(error =>{
return '🥐'; // getEgg에서 에러가 발생하여도 promise chain이 중단되지 않게 함
})
.then(cook)
.then(console.log)
.catch(console.log);
5. Callback - to - Promise (콜백지옥 해결)
// Callback Hell example
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (
(id === "hak" && password == "sae") ||
(id === "coder" && password == "academy")
) {
resolve(id);
} else {
reject(new Error("not found"));
}
}, 2000);
});
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === "hak") {
resolve({ name: "hak", 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);
출처 : 드림코딩엘리 https://www.youtube.com/channel/UC_4u-bXaba7yrRz_6x6kb_w