11. JS Basic (Promise)

Changmok LEE·2023년 2월 23일

Promise

Promise is a JavaScript object for asynchronous operation.
(비동기적인 것들을 실행 할 때 CallBack 함수 대신 유용하게 쓸 수 있는 object)

Promise의 두가지 Point

  • State
  • Producer vs Consumer

State

pending(operating 수행 중일 때) -> fulfilled or rejected(operating 완료 되었을 때)

1. Producer (Promise 만들기)

  • 비동기적으로 일을 처리하는 Promise 생성
  • executor라는 CallBack 함수 전달해 주어야함
  • promise를 만드는 순간 우리가 전달한 executor(resolve, reject) 라는 callback함수가 바로 실행
  • when new Promise is created, the executor runs automatically. -> 불필요한 network 통신 발생하지 않도록 주의
var Promise: PromiseConstructor
new <any>(executor: (resolve: (value: any) => void, reject: (reason?: any) => void) => void) => Promise<any>
const promise = new Promise((resolve, reject) => {
    // doing some heavy work (ex. network, read files)
    conmsole.log('doing something');
    // 데이터 가저오는 시간 가정
    setTimeout(() => {
        // resolve('eelkom');
        reject(new Error('no network')) // reject는 보통 Error라는 object를 통해 값을 전달
    }, 2000);
});

2. Consumers: then, catch, finally(Promise 사용하기)

promise
    .then((value) => { // value == resolve의 전달 값이 들어감
        console.log(value); // eelkom

    }) // then은 promise를 return == chaining
    .catch(error => {
        console.log(error); // Error: no network
    })
    .finally(() => { // 성공과 실패 상관없이 실행
        console.log('finally');
    });

3. Promise Chaining

const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
})

fetchNumber
    .then(num => num * 2) // 1 * 2 = 2
    .then(num => num * 3) // 2 * 3 = 6
    .then(num => {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(num - 1), 1000);
        });
    })
    .then(num => console.log(num)); // 5

4. Error Handling

const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('chicken'), 1000);
    });

const getEgg = hen =>
    new Promise((resolve, reject) => {
        // setTimeout(() => resolve(`${hen} => egg`), 1000);
        setTimeout(() => reject(new Error(`error! ${hen} => egg`)), 1000);
    });

const cook = egg =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => Fried egg`), 1000);
    });

getHen() // chicken => egg => Fried egg
    .then(getEgg) // == then(hen => getEgg(hen)) -> 생략가능
    .catch(error => { // 오류 처리 잘하자
        return 'bread';
    }) // bread => Fried egg
    .then(cook) // == then(egg => cook(egg))
    .then(console.log) // == then(meal => console.log(meal))
    .catch(console.log); // Error: error! chicken => egg

5. Callback Hell to Promise

  • before (Callback Hell)
// 임시 back-end 구성
class UserStorage {
    // back-end 통신시간 존재한다고 가정
    loginUser(id, password, onSuccess, onError) {
        setTimeout(() => {
            if (
                (id === 'eelkom' && password === 'lee') ||
                (id === 'coder' && password === 'lee')
            ) {
                onSuccess(id);
            } else {
                onError(new Error('not found'));
            }
        }, 2000);
    }
    getRoles(user, onSuccess, onError) {
        setTimeout(() => {
            if (user === 'eelkom') {
                onSuccess({ name: 'eelkom', role: 'admin' });
            } else {
                onError(new Error('no sccess'));
            }
        }, 1000);
    }
}

// back-end 불러오기
const userStorage = new UserStorage(); // class 생성
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
    id,
    password,
    (user) => {
        userStorage.getRoles(
            user,
            (userWithRoles) => {
                alert(`Hello ${userWithRoles.name}, you have a ${userWithRoles.role} role`);
            },
            (error) => {console.log(error)}
        );
    },
    (erorr) => {console.log(error)}
);
  • After (Promise)
// 임시 back-end 구성
class UserStorage {
    // back-end 통신시간 존재한다고 가정
    loginUser(id, password) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (
                    (id === 'eelkom' && password === 'lee') ||
                    (id === 'coder' && password === 'lee')
                ) {
                    resolve(id);
                } else {
                    reject(new Error('not found'));
                }
            }, 2000);
        });
    }
    getRoles(user) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (user === 'eelkom') {
                    resolve({ name: 'eelkom', role: 'admin' });
                } else {
                    reject(new Error('no sccess'));
                }
            }, 1000);
        });

    }
}

// back-end 불러오기
const userStorage = new UserStorage(); // class 생성
const id = prompt('enter your id');
const password = prompt('enter your password');

userStorage.loginUser(id, password)
    .then(userStorage.getRoles) // user => userStorage.getRoles(user)
    .then(user => alert(`Hello ${user.name}, you have a ${user.role} role`))
    .catch(console.log); 
profile
이창목

0개의 댓글