javascript | Async와 await + Promise APIs (with 드림코딩)

하영·2024년 6월 21일
0

JavaScript

목록 보기
10/29

개인사정 이슈로..^^ 오랜만에 남기는 벨로그
저번에 이어서 Promise에 대해 복습하면서 추가 정리를 해보려한다.
유데미 강의도 좋았지만 다른 예시와 한국말로 된 강의로 이해하고 싶어서 드림코딩으로 다시 정리해봤다.

Promise 복습

동기적으로 실행되는 javascript를 비동기적으로 실행할 수 있도록 해주는 것

  • Synchronous callback(즉각적, 동기적)
  • Asynchronous callback(나중에, 언제 실행될지 모름)

Callback Hell을 Promise로 간결하게 바꿔보기

예시:

class UserStorage {
    loginUser(id, password, onSuccess, onError) {
        setTimeout(() => {
            if (id === 'ellie' && password === 'dream' ||
                id === 'coder' && password === 'acacdemy'
            ) {
                onSuccess(id);
            } else {
                onError(new Error('not Found'));
            }
        }, 2000);
    }

    getRoles(user, onSuccess, onError) {
        setTimeout(() => {
            if (user === 'ellie') {
                onSuccess({ name: 'ellie', role: 'admin' });
            } else {
                onError(new Error('no access'));
            }
        }, 1000)
    }
}

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
    id,
    password,
    user => {
        userStorage.getRoles(
            user,
            userWithRole => {
                alert(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
                );
            },
            error => {
                console.log(error);
            }
        );
    },
    error => {
        console.log(error);
    }
);

Promise로 바꾸기

class UserStorage {
    loginUser(id, password) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
            if ((id === 'ellie' && password === 'dream') ||
                (id === 'coder' && password === 'acacdemy')
            ) {
                resolve(id);
            } else {
                reject(new Error('not Found'));
            }
        }, 2000);
      })
    }

    getRoles(user) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (user === 'ellie') {
                resolve({ name: 'ellie', role: 'admin' });
            } else {
                reject(new Error('no 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 ${user.name}, you have a ${user.role} role`))
.catch(console.log);

정리한 코드 해석

  1. onSuccess, onError 는 Promise를 활용하였기 때문에 더이상 필요하지 않다.
    onSuccess -> resolve 로, onError -> reject로 바꿔서 정리한다.

  2. loginUser 함수를 실행할 때는 .then.catch 를 활용하여 깔끔한 코드로 바꾼다.
    (loginUser 의 id와 password가 호출되면 // gerRoles 함수를 실행시키고 // 맞다면 경고창으로 유저의 이름과 관리자인지 아닌지를 띄운다.



Async와 await

Promise 를 사용해서 깔끔해졌지만 함께 사용했을 때 더 간결하고 보기 좋게 사용할 수 있는 asyncawait!
⭐️모든 코드를 asyncawait로 쓴다고 좋은 것이 아니라 때마다 Promise가 필요할 때도 있고 Async와 await를 사용해야할 때도 있다는 점

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getApple() {
    await delay(2000);
    // throw 'error'
    return '🍎';
}

async function getBanana() {
    await delay(1000);
    return '🍌';
}

function pickFruits() {
    return getApple().then(apple => {
        return getBanana().then(banana => `${apple} + ${banana}`);
    });
}

//사과와 바나나 함수 각각 Promise 없는 버전 (getApple 함수가 호출될 때까지 시간이 걸리게 됨)
async function pickFruits() {
    const apple = await getApple();
    const banana = await getBanana();
    return `${apple} + ${banana}`;
}

pickFruits().then(console.log);

delay 라는 함수를 활용하여 getApple()getBanana() 함수를 비동기적으로 실행시킨다.
getApple() 은 사과🍎, getBanana() 는 바나나🍌 를 콘솔창에 보여준다.

  • async 는 function 앞에 적어서 사용한다.
  • await 은 async와 함께 쓰여진다.

위 코드에서 보면 사과와 바나나는 누가 먼저 출력이 되든 순서가 상관없는 함수이다.
이처럼 서로 관련이 없을 경우에는 병렬적 으로 실행되도록 만든다.

function pickFruits() {
    const applePromise = getApple(); //만들자마자 함수 실행
  	const bananaPromise = getBanana(); //만들자마자 함수 실행
  	const apple = await applePromise;
  	const banana = await bananaPromise;
  
}

pickFruits().then(console.log);

const applePromise = getApple(); 처럼 만들자마자 기다리지 않고 함수가 실행되도록 만들어준다.
하지만 실제로 이런 코드를 사용하지 않으면 유용한 Promise APIs 를 활용하는데,
바로 all, race 이다.


유용한 Promise APIs

function pickAllfruits() {
    return Promise.all([getApple(), getBanana()])
        .then(fruits => fruits.join(' + '));
}

pickAllfruits().then(console.log);

function pickOnlyOne() {
    return Promise.race([getApple(), getBanana()]);
}

pickOnlyOne().then(console.log);
  • race : iterable 안에 있는 프로미스 중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부한다.
    ⭐️ 전달받은 iterable이 비어 있을 경우, 반환한 프로미스는 영원히 대기 상태

  • all : 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환한다.
    ⭐️ 주어진 프로미스 중 하나가 거부하는 경우, 첫 번째로 거절한 프로미스의 이유를 사용해 자신도 거부



콜백지옥 함수들을 바꿔보면서 동기/비동기 활용하고 Promise가 좋을지 async,await이 좋을지 고민해봐야겠다...
Promise.. 할 수 있게찌...🥲


출처

profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글

관련 채용 정보