할머니의 콤퓨타 도전기

(JavaScript) async & await 본문

Web Front-end/Javascript

(JavaScript) async & await

ji.o.n.e 2021. 5. 5. 14:06

Promise

  • javascript에서 제공하는 비동기를 간편하게 처리할 수 있도록 도와주는 object
  • 정해진 장시간의 기능을 수행하고나서, 정상적으로 기능이 수행되어졌다면 성공의 메세지와 함께 처리된 결과값을 전달해줌
  • 기능을 수행하다가 문제가 발생하면 에러를 전달
  • 언제 데이터를 받아올 지는 모르겠지만 promsie object를 갖고있고 then이라는 콜백함수만 등록하면 준비되는대로 콜백함수 불러줄게!

async & await

  • clear style of using promise
  • promise를 조금 더 간결하고 동기적으로 실행되는 것 처럼 보이게 만들어줌
  • promise 위에 조금 더 간편한 API 제공
    • syntatic sugar: 기존에 존재하는 것 위에 또는 감싸서 간편한 API 제공
function fetchUser() {
    // do network request in 10 secs..
    return 'jiwon';
}
const user = fetchUser(); // 비동기적인 처리를 하지않으면 사용자의 데이터를 받아오는데 10초가 걸림
// 만약 뒤에서 웹페이지의 UI 표시 기능 수행 코드들은 끝나는 동안 웹페이지에 표시되지 않음
console.log(user);

상당한 시간이 소요되는 작업(데이터를 받아오거나 파일을 읽을 때)에 이처럼 비동기 처리를 해주지 않으면 해당 작업이 완료되는 동안 코드 뒷 부분이 수행되지 않는다. 따라서 웹페지지 UI 표시 기능을 수행하는 코드들이 있을 경우 작업이 완료되기 전까지 표시되지않는다.

 

function fetchUser() {
    return new Promise((resolve, reject) => {
        // do network request in 10 secs..
        resolve('jiwon');
    });
}
const user = fetchUser();
user.then(console.log);

따라서 promise를 이용해 이처럼 비동기처리를 해줄 수 있다. 이때 async를 이용하면 바로 promise로 만들어준다.

 

async

async function fetchUser() { // async 이용하면 바로 promise로 만들 수 있음 
    return 'jiwon';
}
const user = fetchUser();
user.then(console.log);
console.log(user); // Promise { <state>: "fulfilled", <value>: "jiwon" }

 

await

  • async가 붙은 함수 안에서만 사용 가능
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
    await delay(1000); // await을 쓰게되면 delay()가 끝날 때 까지 기다려줌
    // throw 'error';
    return '🍎';
}

async function getBanana() {
    await delay(1000);
    return '🍌';
}
function getBanana() { // 이처럼 chaining을 하는 것 보다 위처럼 동기적인 코드를 쓰는 것 처럼 만드는게 좋음
    return delay(30000)
        .then(() => '🍌');
}

function pickFruits() {
    return getApple().then(apple => {
        return getBanana().then(banana => `${apple} + ${banana}`
        );
    })
} // promise도 너무 중첩적으로 chaining을 하게되면 콜백지옥과 비슷한 문제점 발생
pickFruits().then(console.log);

이처럼 promise도 너무 중첩적으로 chaining을 하게 되면 콜백지옥과 비슷한 문제점이 발생한다. 따라서 async & await를 이용해 동기적인 코드처럼 작성하는게 좋다.

 

async function pickFruits() {
	const apple = await getApple();
    const banana = await getBanana(); // getApple()과 getBanana()를 순차적으로 진행하면 비효율적. 서로 연관되어있지 않음
    return `${apple} + ${banana}`;
}
pickFruits().then(console.log);

getApple()과 getBanana()는 서로 연관되어있지않다. 따라서 이를 순차적으로 진행하면 총 2초가 걸리게 되므로 비효율적이다.

async function pickFruits() {
	const applePromise = getApple();
    const bananaPromise = getBanana();
    const apple = await applePromise; // 동기화
    const banana = await bananaPromise; // 1s만에 병렬적으로 수행가능
    return `${apple} + ${banana}`;
} // 동시에 수행이 가능한 경우에는 이처럼 작성하지는 않음
pickFruits().then(console.log);

따라서 이와 같이 작성할 수 있다. promise는 만들어지는 순간 지정한 콜백함수가 바로 수행되기 때문에 병렬적으로 getApple()과 getBanana()를 실행하고 await를 이용해 동기화를 시켜준다. 따라서 1s만에 병렬적으로 수행이 가능하다. 하지만 보통 이런식으로 작성하지는 않고 Promise API 중 하나인 all()을 사용한다.

 

useful Promise APIs

  • all()
    • promise 배열을 전달하게되면 모든 promise들이 병렬적으로 수행
function pickAllFruits(){
    return Promise.all([getApple(), getBanana()]) // all(): promise 배열을 전달하게되면 모든 promise들이 병렬적으로 수행
    .then(fruits => fruits.join(' + '));
}
pickAllFruits().then(console.log);

 

  • race()
    • 배열에 전달된 promise 중에서 가장 먼저 값을 리턴하는 것만 전달되어짐
function pickOnlyOne(){ 
    return Promise.race([getApple(), getBanana()]); // race(): 배열에 전달된 promise 중에서 가장 먼저 값을 리턴하는 것만 전달되어짐
}
pickOnlyOne().then(console.log);

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

(JavaScript) classList  (0) 2021.05.12
JavaScript 최신 문법 (ES6, ES11)  (0) 2021.05.05
(JavaScript) Promise  (0) 2021.05.05
(JavaScript) Callback  (0) 2021.05.05
(JavaScript) JSON  (0) 2021.05.05
Comments