ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 - async / await?
    JavaScript/동작원리 2020. 9. 19. 15:42

     

    aysnc await이란?

    콜백 함수나 프로미스처럼 비동기를 다루는 자바스크립트 패턴 중 하나이며 가장 최근에 나온 Es7문법이다.

    프로미스랑은 조금 다른 사용법을 가지고 있으며 프로미스를 이용하는 아이라고 생각하면 된다.

     

    aysnc 키워드

    예제를 통해 async 키워드부터 알아보자.

    // async 키워드가 없는 일반 함수
    function myFunc(){
    	return 'func';
    }
    
    // async 키워드가 있는 함수
    async function myAsync(){
    	 return 'async';
    }
    
    console.log(myFunc());
    console.log(myAsync());

    출력 화면

    출력 결과를 보면 서로 다른 것을 확인할 수 있다.

    • 첫 번째 myFunc() 함수는 생각했던 대로 func가 반환되어 출력되었고,

    • 두 번째 myAsync() 함수는 async를 선언하고 반환했을 때 결괏값이 Promise가 출력되었다.

    즉, function 앞에 async를 붙이면 해당 함수는 항상 프로미스를 반환한다는 의미이다.

     

    then() 사용

    그러면 이제 async 키워드가 포함된 함수는 프로미스를 반환하기 때문에 then()을 사용할 수 있다.

    예제를 살펴보면,

    async function myAsync(){
    	return 'async';
    }
    
    myAsync().then((result) => {
    	console.log(result); // async
    })

    프로미스를 반환하고 then()으로 받게 되는 인자 result는 바로 return 값을 의미한다.

    프로미스 패턴에서도 then()을 사용했었는데, 거기서 then()의 리턴 값이 곧 다음 프로미스의 결괏값으로 넘어가듯이

    여기서도 마찬가지로 myAsync() 함수 내에서 반환된 값은 호출했을 때 return 되는 프로미스를 then()에 의해서 등록된 함수의 인자(예를 들어 result) 값으로 넘기게 된다.

    그래서 async라는 값이 출력된 것이다.

     

     

    await

    이제 async의 단짝 await은 어떻게 쓰는 건가?

    await는 async 함수 안에서만 동작하며, 이름에서부터 알 수 있듯이 await은 무언가를 기다리는 것을 말한다.

    그러면 뭘 기다리냐면?

    프로미스가 resolve가 돼서 결괏값이 넘어올 때까지 기다리는 것을 말한다.

    예제를 통해 알아보자.

    function delayP(sec){
    	return new Promise((resolve, reject) => {
        	setTimeout(() => {
            	resolve(new Date().toISOString());
            }, sec * 1000);
        });
    }
    
    async function myAsync(){
    	// 비동기 동작하는 함수
    	delayP(3).then((time) => {
        	console.log(time); // 3초 뒤에 시간 출력
        });
    	return 'async';
    }
    
    myAsync().then((result) => {
    	console.log(result); // async가 먼저 출력
    });

    출력하면 비동기 동작하는 delayP() 함수가 실행돼서 async가 먼저 찍히고, 그러고 나서 3초 뒤에 시간이 찍힌다.

     

    하지만 만약 3초 동안 기다리고 async를 출력하고 싶다면?

    function deleyP(sec){
    	return new Promise((resolve, reject) => {
        	setTimeout(() => {
            	resolve(new Date().toISOString());
            }, sec * 1000);
        });
    }
    
    async function myAsync(){
    	await delayP(3)
    	return 'async';
    }
    
    myAsync().then((result) => {
    	console.log(result); // 3초 뒤에 async 출력
    });

    aysnc 키워드가 포함된 함수이기 때문에 await을 쓰면 가능하게 할 수 있다.

    간단히 await을 붙이면, delayP() 함수의 프로미스가 resolve 될 때까지 다음 줄로 넘어가지 않게 된다.

    그 이유는 delayP() 함수는 new promise로 명시적으로 선언된 프로미스이며, await이 프로미스가 resolve 될 때까지 다음 줄로 넘어가지 않게 명령하기 때문이다.

    즉, await을 통해서 기다리게 했다가 나중에 return이 가능하다는 의미이다.

    만약에 async 함수가 아니었다면 delayP()의 동작을 기다리는 일은 없을 것이다.

     

    만약 일반 변수처럼 await을 사용하고 싶다면?

    function deleyP(sec){
    	return new Promise((resolve, reject) => {
        	setTimeout(() => {
            	resolve(new Date().toISOString());
            }, sec * 1000);
        });
    }
    
    async function myAsync(){
    	const time = await delayP(3);
        console.log(time);
    	return 'async';
    }
    
    myAsync().then((result) => {
    	console.log(result); // 3초 뒤에 async 출력
    });

    여기서 변수 time에 시간 값을 받는다면, 프로미스가 resolve 돼서 then()에서 받은 결과 값처럼 그 값을 마치 일반 함수에서 return값을 받듯이 const time = await deplayP() 선언이 가능하다.

     

    여기서 만약에 then을 붙이고 다른 값을 반환하면?

    아까처럼 time을 받는다고 치고 return 'x'를 하면 결괏값은 바로 x이다.

    function deleyP(sec){
    	return new Promise((resolve, reject) => {
        	setTimeout(() => {
            	resolve(new Date().toISOString());
            }, sec * 1000);
        });
    }
    
    async function myAsync(){
    	const result = await delayP(3).then((time) => {
        	return 'x';
        })
        console.log(result);
    	return 'async';
    }
    
    myAsync().then((result) => {
    	console.log(result); // 3초 뒤에 async 출력
    });

     

    그리고 꼭 프로미스를 리턴하는 아이가 아니더라도 일반 함수 앞에 await을 넣어도 아무런 상관없이 찍힌다.

    function deleyP(sec){
    	return new Promise((resolve, reject) => {
        	setTimeout(() => {
            	resolve(new Date().toISOString());
            }, sec * 1000);
        });
    }
    
    function normalFun(){
    	return 'wow';
    }
    
    async function myAsync(){
    	const result = awiat nomalFun();
        console.log(result);
    	return 'async';
    }
    
    myAsync().then((result) => {
    	console.log(result); // 3초 뒤에 async 출력
    });

     

     

     

    🎈 정리하자면

    • aysnc는 일반 함수를 프로미스로 return 하는 함수로 만들어준다.

    • aysnc가 포함된 함수에서 await을 사용하면  기다리는 동안 return을 하지 않는 것을 말하며, 또 다른 말로는 프로미스의 resolve를 나중에 하는 것을 의미한다.

    • 프로미스를 return 하는 delayP() 함수나 프로미스를 리턴하는 async 함수, 둘 다 프로미스를 return 하기 때문에 사용법은 같다. 그렇기 때문에 호출했을 때 then()을 통해 resolve 된 값을 받는 것이다.

    • 프로미스에서는 명시적으로 쓸 때는 resolve 함수를 인자로 받아서 결괏값을 resolve로 넘겨주는데, async는 다르게 일반 함수에서 사용하기 때문에 그 안에서 return 하는 값은 프로미스의 resolve값이 된다.

    • async와 쌍을 이루는 await는 말 그대로 뒤에 어떠한 동작을 기다리는 것을 의미하며, 만약 프로미스면 프로미스가 resolve 되도록 기다리고 그냥 함수이면 일반 함수처럼 리턴 값이 반환할 때까지 기다리는 것이 특징이다.

     

    📝 느낀 점

    나름대로 aysnc await의 기본 개념과 사용법을 정리해보았다.

    나중에 에러 처리 내용도 추가할 예정이다.

    promise와 aysnc await 둘 중 하나만 쓰는 것이 아니라, 쓰는 목적에 따라 코드 로직을 표현해야 한다.

    왜냐하면, 프로미스로 표현하기 쉬운 것이 있고, aysnc await으로 사용해서 표현하기 쉬운 경우가 있기 때문이다.

    어느 하나를 무조건 안 쓴다거나 뭔가 서로 다른 것이 아니라 서로 잘 조합해서 잘 써야 하는 것 같다.

     

    댓글

Designed by Tistory.