# JavaScript Promise

### Promise

* promise: 비동기를 간편하게 처리 할 수 있게 해주는 object
* 정해진 장시간의 기능을 수행하고 성공해진 메세지와 함께 기능 수행 아니면 에러가 뜸&#x20;

### Producer

```javascript
// Promise is a JavaScript object for asynchronous peration
// state (상태):pending -> fulfilled or rejected 
// producer vs cosumer 만드는사람/ 소비하는사람

const promise = new Promise((resolve, reject) => {
// when new Promise is created, the ececutor runs automatically.
//doing some heavy work (network, read files)
// 읽어오는것, 네트워크 이런것들은 무겁기때문에 비동기로 처리하는것이 좋다
// promise가 만들어진 순간 바로 수행을 하게됨
// 사용자가 버튼을 눌렀을때 네트워크가 작동되게 하는것은 바로 수행되기때문에 맞지않음 
    console.log('doing something...');
    setTimeout(() => {
       resolve('ellie')
     //reject(new Error('no network'));
    }, 2000);
});
```

### consumers : then, catch, finally

```javascript
// 약속된 값을 잘 받아온다면 전달되서 결과물을 출력시킴 
// value의 값은 위에 처리과정이 잘 진행되 ellie라고 처리된 값이 들어오게 됨
//than은 promise로 리턴되고 다시 catch 를 붙이게 된다.
    promise.then((value) => {
    console.log(value);
    })
    .catch(error => {
        console.log(error);
    })
   .finally(() => {
       console.log('finally'); //성공하던 실패하던 상관없이 어떤기능을 마지막으로 수행하고 싶을때 finally를 사용함
   });

```

###

### promise chaining

```javascript
const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000); // Promise 는 1초 있다가 숫자 1을 전달
});
fetchNumber
    .then(num => num * 2) // 2
    .then(num => num * 3) //6
    .then(num => {
        return new Promise((resolve, reject) => { // 새로운 Promise를 리턴
        setTimeout(() => resolve(num - 1), 1000); //5
        });
    })
    .then(num => console.log(num)); //5
```

###

### Error Handling

```javascript
// 암닭을 받아오는 
const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('🐔'), 1000);
    });
// 암닭을 받아서 닭으로부터 달걀을 얻어오는 
const getEgg = hen =>
    new Promise((resolve, reject) => {
        setTimeout(() => reject(new Error(`ERROR! ${hen} => 🥚`)), 1000);
    });
// 달걀을 받아와서 요리하는것 
const cook = egg =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
    }); 

// 계란을 받아오는것에 문제가 생겨도 다른것으로 대체하는것 
// 해당부분에서 문제가 생긴후에도 catch를 이용해 error를 처리하고 기능을 진행 할 수 있다. 
getHen() 
    .then(getEgg)
    .catch(error => { // 에러 핸들링 계란을 받을때 문제가 생긴다면 -> 다른것을 리턴해줌
        return '🥗';
    })
    .then(cook)
    .then(console.log)
    .catch(console.log); // 위의 핸들링이 없으면 에러 메세지(ERROR! 🐔 => 🥚)가 뜸 
```

###

### 콜백지옥 코드수정

```javascript
class UserStorage {
    loginUser(id, password){
        return new Promise((resolve, reject) => 
             setTimeout(() => {
                if (
                    (id === 'ellie' && password === 'dream') ||
                    (id === 'coder' && password === 'academy')
                ) {
                   resolve(id);
                } else{
                   reject(new Error('not found')); // 에러 'not found'
                }
             }, 2000);
        });

    // 사용자가 엘리이면 이름은 엘리고 role 은 어드민인 값을 전달해주고 아니면 not access라고 전달 
 
    getRoles(user) {
      return new Promise((resolve, reject) => {
          if (user === 'ellie') {
               resolve({ name: 'ellie', role: 'admin' });
            } else {
               reject(new Error('no access')); // 에러 'not 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 ${userWithRole.name}, you have a ${userWithRole.role} role`));
.catch(console.log);       

```
