할머니의 콤퓨타 도전기

(JavaScript) Promise 본문

Web Front-end/Javascript

(JavaScript) Promise

ji.o.n.e 2021. 5. 5. 11:29

Promise

  • Promise is a JavaScript object for asynchronous operation.
  • State : pending(promise가 만들어져서 지정한 operation이 수행중일 때) -> fulfilled(operation을 성공적으로 끝냄) or rejected
  • Producer(원하는 기능을 수행해서 해당하는 데이터를 만들어냄) vs Consumer(원하는 데이터를 소비함)

 

Producer

  • when new Promise is created, the executor runs automatically.
    • promise를 만드는 순간 우리가 전달한 executor 콜백함수가 바로 실행
  • 만약 네트워크 요청을 사용자가 요구했을 때만(ex. 버튼을 눌렀을 때) 해야하는 경우라면 아래처럼 작성하면 요구하지도 않았는데 불필요한 네트워크 통신 발생
  • 네트워크에서 데이터를 받아오거나 파일에서 큰 데이터를 읽어오는 과정은 시간이 꽤 걸림
    • 따라서 이를 synchronous로 처리하게 되면 데이터를 받아오거나 읽어오는 동안 다음 라인의 코드가 실행되지않음
    • 시간이 걸리는 일들은 promise를 만들어서 비동기적으로 처리하는 것이 좋음
const promise = new Promise((resolve, reject) => {
    // Promise는 class이기 때문에 new keyword로 object 생성
    // Promise의 생성자는 executor라는 콜백함수 전달해줘야힘
    // executor는 또 다른 2가지의 콜백함수를 받음
    // resolve -> 기능을 정상적으로 수행해서 마지막에 최종 데이터 전달
    // reject -> 기능을 수행하다가 중간에 문제가 생기면 호출
    // doing some heavy work (network, read files)
    // 네트워크에서 데이터를 받아오거나 파일에서 큰 데이터를 읽어오는 과정은 시간이 꽤 걸림
    // 따라서 이를 synchronous로 처리하게 되면 데이터를 받아오거나 읽어오는 동안 다음 라인의 코드가 실행되지않음
    // --> 시간이 걸리는 일들은 promise를 만들어서 비동기적으로 처리하는 것이 좋음
    console.log('doing something...');
    // promise를 만드는 순간 우리가 전달한 executor라는 콜백함수가 바로 실행됨
    // 만약 promise 안에 네트워크 통신을 하는 코드를 작성했다면, 
    // promise가 만들어지는 그 순간 바로 네트워크 통신 수행하게 됨
    setTimeout(() => {
        resolve('jiwon'); // 성공적으로 네트워크에서 받아오거나 파일에서 읽어온 데이터를 resolve 콜백함수를 통해 전달
    }, 2000);
});

 

Consumers

  • then, catch, finally
    • then
      • promise가 정상적으로 수행이되어서 마지막에 최종적으로 resolve 콜백함수를 통해서 전달한 값이 value의 파라미터로 전달되어짐
promise.then((value) => { // 값이 정상적으로 수행이 된다면
    console.log(value); // value: promise가 정상적으로 잘 수행이되어서 마지막으로 resolve 콜백함수에서 전달된 값이 들어옴
}) // then을 호출하게 되면 다시 promise가 return되므로 catch 등록 가능
    .catch(error => {
        console.log(error);
    })
    .finally(() => { // finally: 성공 실패 여부 상관없이 마지막으로 수행
        console.log('finally');
    });

 

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
// then : 값을 바로 전달할 수도 있고, promise 전달도 가능

 

Error Handling

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

getHen()
    .then(getEgg) // 콜백함수를 전달할 때, 받아오는 value를 다른 함수로 호출하는 경우 생략 가능 hen => getEgg(hen)
    .catch(error => {
        return '🍞'; // 전달되어진 에러를 잘 처리해서 대체 
    }).then(cook)
    .then(console.log)
    .catch(console.log);

콜백함수를 전달할 때, 받아오는 value를 다른 함수로 호출하는 경우 생략이 가능하다.

 

jioneprogstdy.tistory.com/119

 

(JavaScript) Callback

JavaScript is synchronous! Execute the code block in order after hoisting. hoisting이 된 이후부터 code가 작성한 순서에 맞춰서 하나씩 동기적으로 실행 정해진 순서에 맞게 코드가 실행되는 것 hoisting va..

jioneprogstdy.tistory.com

마지막으로 이전 포스팅에서 Callback hell을 작성했다. promise를 이용해 이를 수정할 수 있다.

class UserStorage {
    loginUser(id, password) { // 콜백 더이상 전달받지 않아도 됨
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if ((id === 'jiwon' && password === '1234') ||
                    (id === 'coder' && password === '0000')
                ) {
                    resolve(id);
                } else {
                    reject(new Error('not found'));
                }
            }, 2000);
        });
    };

    getRoles(user) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (user === 'jiwon') {
                    resolve({ name: 'jiwon', role: 'admin' });
                } else {
                    reject(new Error('no access'));
                }
            }, 1000);
        });
    }
}

// 1. 사용자에게 id, password 입력받아옴
// 2. 받아온 id, password로 login
// 3. login이 성공적이라면 login한 사용자의 id를 다시 받아옴. 받아온 id를 이용해 역할 요청
// 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);

 

'Web Front-end > Javascript' 카테고리의 다른 글

JavaScript 최신 문법 (ES6, ES11)  (0) 2021.05.05
(JavaScript) async & await  (0) 2021.05.05
(JavaScript) Callback  (0) 2021.05.05
(JavaScript) JSON  (0) 2021.05.05
(Javascript) Array APIs  (0) 2021.05.04
Comments