TIL018 JavaScript: Promise

Somi·2021년 5월 24일
0

JavaScript

목록 보기
15/27
post-thumbnail

콜백지옥에서 구원해줄 Promise

Promise란 무엇인가

  • Promise는 비동기적인 것을 수행할 때 콜백함수 대신에 유용하게 쓰일 수 있는 오브젝트
  • promise는 어떤 일의 진행상태를 나타내는 객체로 진행의 "상태"와 "값"이라는 속성을 갖고 있다.

✔️ 공부 포인트 1. state(상태): pending(promise가 만들어진 후 operation이 수행 중일 때) -> fulfilled(operation을 성공적으로 끝냈을 때) or rejected(오류가 생겼을 때)
✔️ 공부 포인트 2. producer(정보제공자, promise object) vs consumer(정보소비자)

1. Producer

  • 새로운 프로미스가 만들어질 때 executor라는 함수가 바로 실행된다.(네트워크 통신 수행)
  • 따라서 사용자가 버튼 등을 눌렸을 때 네트워크 통신을 실행하는 기능을 만드려면 이 사실을 유의해야함.
const promise = new Promise((resolve, reject)=> {
    //doing some heavy work(network, read files은 시간이 걸리기 때문에 동기적으로 처리할 경우 다음 라인의 코드가 처리되는데 시간이 걸리기때문에 비동기적으로 처리하는 것이 좋음)
    console.log('doing something')
    setTimeout(() => {
        resolve('somi');
        // reject(new Error('no network'))
    }, 2000);
})
  • promise가 만들어진 순간 안의 함수가 실행된다.

2. Consumer: then, catch, finally

promise
    .then((value) => {
        console.log(value);
    })
    .catch(error => {
        console.log(error);
    })
    .finally(()=>{
        console.log('finally')
    })
  • reject를 사용할 경우: "Error: no network"
  • resolve를 사용할 경우: "somi"
  • finally는 성공여부와 상관없이 어떤 기능을 마지막으로 수행하고 싶을 때 사용한다.

3. Promise chaining

  • 비동기적인 여러가지를 동시에 묶어서 처리할 수도 있다.
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)); //5

4. Error Handling

  • catch를 이용하면 error가 제일 밑으로 내려간다.
const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('hen'), 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} => fried egg`), 1000);
    });

getHen()
    .then(getEgg)
    .catch(error =>{
        return 'bread';
    })
    .then(cook)
    .then(console.log)
    .catch(console.log);

//위는 아래와 같다. 인자가 같으면 생략가능!
// .then(hen => getEgg(hen))
// .then(egg => cook(egg))
// .then(meal => console.log(meal))

콜백함수를 promise로 대체하자!

class UserStorage {
    loginUser(id, password){
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (
                    (id === 'somi' && 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 === 'somi'){
                    resolve({ name: 'somi', role: 'admin' });
                }else{
                    reject(new Error('no access'));
                }
            }, 1000);
        })
    }
}


const userStroage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');

userStroage
    .loginUser(id, password)
    .then(userStroage.getRoles) 
    .then(user => alert(`hello! ${user.name}, you have a ${user.role} role.`))
    .catch(console.log)

이렇게 만들면 아래의 콜백지옥에서 헤어나올 수 있다.

userStroage.loginUser(
    id, 
    password,
    user => {
        userStroage.getRoles(
            user,
            userWithRole => {
                alert(`hello! ${userWithRole.name}, you have a ${userWithRole.role} role.`)
            },
            error => {
                console.log(error);
            }
        );
    },
    error => {
        console.log(error);
    }
);

0개의 댓글

관련 채용 정보