JavaScript

드림코딩 : JS - 12. Promise, Callback 지옥을 Promise로 예쁘게!

식초 2020. 10. 20. 22:08
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
'use strict';
 
//Promise는 자바스크립트 안에 내장된 object이다
//Promise는 비동기 작업 수행할 때 콜백 대신 사용한다
//State(프로미스의 상태): pending(수행중) -> fulfilled(완료) or rejected(문제생김) 상태가 된다
//Producer vs Consumer : 프로미스의 objects
 
//1. Producer
//주의: 새로운 Promise가 만들어질 때, executor가 자동적으로 바로 실행된다
const promise = new Promise((resolve, reject) => {
    //doing some heavy work (network, read files)
    console.log('doing something...');
    setTimeout(() => {
        resolve('sigcho');  //성공적으로 잘함
        //reject(new Error('no network'));  //실패함, 주로 Error 객체 사용, 괄호 안에 에러 이유를 써준다
    }, 2000);
}); 
 
 
 
//2. Consumers: then, catch, finally 이용해서 값 받아올 수 있다
promise 
    .then(value => {  //then 사용: value에는 성공적으로 마친 resolve값인 'sigcho'가 들어온다
        console.log(value);  //2초 있다가 sigcho 출력된다
    })                            
    .catch(error => {  //catch 사용: 에러가 발생했을 때, callback함수
        console.log(error);  //[chaining] then이 Promise 함수를 리턴하기 때문에, 리턴된 Promise의 catch를 등록한다
    })
    .finally(() => {console.log('finally')}); //성공, 실패 상관없이 무조건 마지막에 호출된다
 
 
 
//3. Promise chaining (Promise 연결하기)
const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
});
 
fetchNumber  
    .then(num => num * 2)  //1전달 받고, 2출력
    .then(num => num * 3)  //2 전달 받고, 6출력
    .then(num => {         //then은 값 | Promise(비동기) 전달 모두 가능하다
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(num -1), 1000);
        });
    })
    .then(num => console.log(num)); //6전달 받고, 5출력, 총 2초 소요
 
 
 
//4. Error Handling (오류 잘 처리하자)
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);
    });
 
 
//getHen()  //닭 받아오기
    //.then(hen => getEgg(hen)) //그런다음 닭이용해서 getEgg함수 호출
    //.then(egg => cook(egg))   //그런다음 달걀로 cook함수 호출
    //.then(meal => console.log(meal)); //그런다음 요리를 콘솔에 출력, 3초 소요
 
getHen() //
    .then(getEgg) //다른 함수로 바로 하나 호출할 경우, 생략 가능, 위와 같은 의미
    .catch(error => {
        return '🍞';  //전달되어진 에러를 잘 처리하면, 빵으로 땜빵을 해준다, 요리 어쨋든 완성!
    })                //에러를 바로잡고 싶으면 catch를 사용해서 바로바로 할 수 있다
    .then(cook)
    .then(console.log)
    .catch(console.log); //에러를 catch가 잡아준다
 
 
cs

 

 

Promise 콘솔 값

 

 

 

 

 

Callback 지옥 -> Promise로 예쁘게!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//Callback Hell example
class UserStorage {
    loginUser(id, password) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if(
                    (id === 'sigcho' && password === 'dream'||
                    (id === 'corder' && password === 'academy')
                ) {
                    resolve(id);
                } else {
                    reject(new Error('not found'));
                }
            }, 2000);
        });
    }
 
    getRoles(user){
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (user === 'sigcho') {
                    resolve({name'sigcho', role: 'admin'});
                } else {
                    reject(new Error('no access'));
                }
            }, 1000);
        });
    }
}
 
//1. id와 password 사용자에게 받아오기
//2. 서버에 login
//3. id를 통해서 role 받아오기
//4. 사용자의 object 출력
 
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);
 
cs