async, await

박진·2021년 3월 16일
0

source:https://johnpapa.net/async-comparisons/

비동기의 꽃라고하는 async와 await에 대해 알아보자.

우선 위의 그림이 비동기과정을 잘 나타낸거같아 이해가 더 쉬워진것같다.

async, await

async-await 는 syntactic sugar라고도 불리는데, syntactic sugar란(기존의 존재(promise API같은) 하는 조금더 편한 api를 제공하는 또는 감싸서 api를 제공하는것)라고한다.

말은 어렵다. 한번 사용해보자. 우선 왜써야하는지에대해 알아보자.

// 백엔드에서 데이터를 가져오는데 10초가 걸리는 함수가 있다고 가정해보자. (fetchUser)

function fetchUser(){
	return 'user';
}

const user = fetchUser();
console.log(user);

designDiv();

function designDiv(){
	let div = document.getElementById('div');
    div.style = 'background-color : blue';
}
    

만약에 fetchUser를 비동기로 처리하지 않을경우에는 아래에 designDiv함수가 10초뒤에 실행되기 때문에 user는 10초동안 기달린후 다음 실행되는 함수를 보게된다. 그러면 매우 불편함을 줄수있기 때문에 비동기적으로 처리를 해야한다.

promise도 쓸수있기에 먼저 한번 써보자.

Source: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

promise는 우선 다음중 하나의 상태를 가지게된다.

  • 대기(pending): 이행하거나 거부되지 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

대기중인 pronmise는 값과 함께 이행(fulfilled)될수도 또는 error로인해 거부(rejected)가될수있다. 이행이나 거부가 되어질때 promise에 연결한 처리기는 then 메서드에 의해 대기열에 오르게된다.

Promise.prototype.then() 및 Promise.prototype.catch() (en-US) 메서드의 반환 값은 다른 프로미스이므로, 서로 연결할 수 있습니다.!

function fetchUser(){
	return new Promise((resolve, resject) =>{
    if (response) {
    	resolve('ellie');
    } reject(new Error("Request is failed"));
    })
}

const user = fetchUser(userName);
user.then(console.log(userName));
	.catch(
    	// 거부 이유 기록
 function(reason) {
            console.log('거부된 프로미스(' + reason + ')');
});

designDiv();

function designDiv(){
	let div = document.getElementById('div');
    div.style = 'background-color : blue';
}

promise는 resolve, resject라는 각각의 callback함수를 받는 executor라는콜백함수를 만들어서 비동기적으로 수행할수있다.

resolve는 성공적으로 이행이되면 .then을 이용하여 처리값을 받을수있고,
reject가 된다면 .catch로 그 문제를 받을수 있게된다.

promise가 길어졌는데... 다시 async를 다시알아보자

async는 이코드안에서 쓰는방법은

간단하다 함수앞에 async만 붙이면된다. 이렇게 되면 fecthUser는 promise를 반환하게 된다.

async function fetchUser(){
	return 'user';
}

const user = fetchUser();
console.log(user);

designDiv();

function designDiv(){
	let div = document.getElementById('div');
    div.style = 'background-color : blue';
}
    

그렇다면 await은?

await은 async가 붙은 함수 안에서만 실행이 가능하다.

	function delay(ms){
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function getApple(){
    	await delay(3000);
        return console.log('apple');
     }
     
     async function getBanana(){
    	await delay(3000);
        return console.log('Banana');
     }
     

getApple, getBanana함수가 delay함수를 호출하게되는데 3초 뒤에 promise리턴하게되고, 여기서 await은 정해진 시간(3초)가 끝날때 까지 기다려준후 getApple, getBanana가 실행된다.

그럼 만약에 저 두 apple, banna가 끝난후 실행되는 함수를 만들고싶다면,

	function delay(ms){
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function getApple(){
    	await delay(3000);
        return console.log('apple');
     }
     
     async function getBanana(){
    	await delay(3000);
        return console.log('Banana');
     }
     
     async function getFruits(){
     	const apple= await getApple();
        const banana = await getBanana();
        return `${apple} + ${banana}`;
      }
      
      getFruits().then(console.log);
     

만야겡 동시다발적으로, 병렬적으로 Apple과 banana를 실행할려면,

	function delay(ms){
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function getApple(){
    	await delay(3000);
        return console.log('apple');
     }
     
     async function getBanana(){
    	await delay(3000);
        return console.log('Banana');
     }
     
     async function getFruits(){
     	const applePromise= getApple();
        const bananaPromise = getBanana();
        const apple = await applePromise;
        const banana = await bananaPromise;
        return `${apple} + ${banana}`;
      }
      
      getFruits().then(console.log);
      
      //또는 간단하게 promise API (Promise.all)를 이용할수있다.
      
    function getFruits(){
    	return Promise.all([getApple(), getBanana()].then(fruits => 
        fruits.join(' + ')
        );
       }
     getFruits().then(console.log);
     
     //또는 어떤것이 먼저 실행되는것을 가져올떄는?? Promise.race라는 API를 이용할수있다.
     
         async function getApple(){
    	await delay(1000);
        return console.log('apple');
     }
     
     async function getBanana(){
    	await delay(3000);
        return console.log('Banana');
     }
     
     
     function pickOnlyOne(){
     	return Promise.race([getApple(), getBanan()]);
       }
       
     pickOnlyOne().then(console.log);
    

만약에 에러를처를 할려면?

	function delay(ms){
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function getApple(){
    	await delay(3000);
        throw 'error'
        return console.log('apple');
     }
     
     async function getBanana(){
    	await delay(3000);
        return console.log('Banana');
     }
     
     async function getFruits(){
     try{
     	const apple= await getApple();
        const banana = await getBanana();
        return `${apple} + ${banana}`;
      } catch(){
    	  
	}      
      getFruits().then(console.log);

throw와 / try, catch메소드를 이용하여 error를 받을수있다.

profile
Hello :)

0개의 댓글