ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • async와 await 그리고 유용한 Promise APIs
    개발언어/JavaScript 2022. 6. 10. 15:59

    async / await

    promise를 계속 chaining하다 코드가 지저분해 지기 쉽상이다. 이런 것 위에 좀더 간편한 api로 async와 await을 사용하면 promise를 좀더 간편하고 간결하게 사용할 수 있게 해주고, promise가 좀 더 동기적으로 실행되는 것 처럼 보일 수 있도록 해준다. 

     

    async와 await 새로운 것이 추가된 것이 아니라 기존에 존재하는 promise 위에 조금더 간편한 api를 제공하는 것이다. 이렇게 기존에 존재하는 것 위에 또는 기존에 존재하는 것을 감싸서 조금더 간편한 api를 제공하는 것을 syntatic sugar라고 한다.

     

    예) JavaScript에서 class는 전혀 새로운 것이 아니라 prototype을 기본으로한  syntatic sugar이다.

     

    무조건 promise를  async 또 는 await으로 변환해서 사용해야 하는 것이 아니라, 각각 필요에 따라 구분해서 사용할 줄 알아야 한다.

     

    비동기처리가 필요한 이유

    JavaScript엔진은 이전의 코드가 끝나야 그 다음 줄의 코드를 실행한다. 즉 동기적으로 코드를 처리한다는 의미이다.

     

    위와 같은 코드를 만나면, JavaScript 엔진은 해당 함수를 실행하기 위해 함수가 선언되어 있는 선언부로 이동한다.

     

    위와 같이 함수가 선언 되어 있는 곳에 도착해서, 함수의 코드 블럭을 실행한다. 해당 코드 블럭이 주석과 같이 10초 정도의 시간이 걸린다고 하면, 10초 정도 코드블럭안에서 머무르고 있다가 10초가 지나서 성공적으로 네크워크 data를 받아 오게 되면, 그제서야 받아온 data가 return 값으로 반환된다.

     

    그리고 그 return된 date가 uer라는 변수에 할당이 되고, 그다음 라인으로 넘어가서 user변수안에 담긴 값이 출력된다.

     


     

    Promise

     위와 같이 return 값을 받는데 오래걸리는 code에 비동기적인 처리를 전혀하지 않으면, 사용자의 data를 받아오는데 10초가 걸린다. 해당 code뒤에 웹 페이지의 UI를 표시하는 기능을 가진 code가 있을경우 네트워크 통신이 끝나는 동안 data가 웹페이지에 표시되지 않기 때문에 사용자는 10초 정도 텅텅비어 있는 웹페이지만 보게 될 것이다.

     

    위와 같이 시간이 오래 걸리는 코드의 경우는 비동기적 처리를 해주어야한다. 비동기 처리 방법중에는 네트워크 통신과 관련된 함수의 반환 값을 Promise 객체로 감싸는 방법도 있다.

     

     

    참고

    https://dodote10.tistory.com/181?category=1016704 

     

    Promise 개념부터 활용

    Promise JavaScript에서 제공하는 비동기 처리를 간편하게 할 수 있도록 도와주는 Object이다. callback 함수를 사용하지 않고 비동기 코드를 깔끔하게 처리하게 해준다. Promise는 정해진 장시간의 기능을

    dodote10.tistory.com

     

     Promise라는 object를 가지고 있을 경우 then 이라는 callback함수만 등록해 놓으면, 네트워크 통신의 결과인 data가 준비되는 대로 등록한 callback함수를 불러준다.

     

     

    그냥 return할 경우

     

    위 코드와 같이 resolve와 reject를 호출하지 않고, 그냥 return을 한뒤 browser에서 console.log를 확인해 보면, Promise가 pending 상태인 것을 확인 할 수 있다. 

     

    => Promise 객체를 생성할 때는 resolve나 reject를 이용해서 완료를 해주어야 한다.

     

     

     

    resolve를 이용할 경우

     

     

    fetchUser()라는 함수는 결국 Promise 객체를 return하기 때문에 변수 user는 Promise type의 인스턴스 변수가 된다.

     

    그래서 위와 같이 user 변수를 통해 then 메소드를 사용할 수 있다.

     


    1.async

    promise를 이용하지 않고도 간편하게 비동기를 작성할 수 있는 방법이 있다. 비동기 처리를 할 함수 앞에 async라는 키워드를 붙여주면 된다. 그러면 번거롭게 return 값을 promise 객체로 감싸지 않아도 자동적으로 함수안에 있는 code block들이 promise로 변환이 되어 진다.

     

    반환 값을 Promise 객체로 바꾼것과 동일한 결과가 console.log에서 출력되고 있는 것을 확인 할  수 있다.

     

     

    2. await

    await이라는 키워드는 async가 붙은 함수 안에서만 쓸수 있다.

     

     

    delay라는 함수는 정해진 시간이 지나면, resolve를 호출하게 되는 Promise 객체를 return 하게 된다.

     

    getApple 함수안에서는 3초를 인자로 같는 delay함수를 사용했다. 이 함수 앞에 await 이라는 키워드를 사용했기 때문에, delay 함수가 수행되는 3초 동안 기다려 준다. 즉 getApple 함수는 3초를 기다리다가 🍎를 return하는 promise인 것이다.

     

     

     

    위 코드에서 두개의 getBanana함수가 하는 기능은 똑같다. 하지만 아래 함수와 같이 Chaining을 하는 것보다 위의 함수처럼 동기적인 코드를 쓰는 것처럼 만들게 되면, delay함수의  수행이 끝나길 기다렸다가 🍌를 return한다는 것을 쉽게 알 수 있다.

     

    Promise도 너무 많이 중첩적으로 Chaining을 하게 되면, callback지옥과 비슷한 문제점이 발생한다.

    하지만 async와 await를 사용하면 아래 함수와 같이 원래 자연스럽게 code를 작성할 수 있기 때문에 간편하다.

     

     

    await 병렬 처리

     

    위의 코드에서는  getApple()과 getBanana() 안에  delay함수실행 으로 인해 두개 함수 모두 다 실행되는데, 각각 1초의 지연이 발행한다.  pcikFruits()함수가 실행되기 위해서 총 2초의 지연이 발생하는 것이다. 하지만  getApple() 함수와 getBanana() 함수가 각각 데이터를 반환하는 것은 서로 연관이 되어있지 않으므로 getApple()의 수행이 끝나길 1초기다린 다음에 getBanana()가 실행이 될 필요가 없다. 즉 두 코드가 직렬적으로 수행될 필요성이 없다는 것이다.

     

    개선 방안

     

    첫번째

    위와 같이 함수를 호출하여 applePromise라는 Promise 형태의 인스턴스 변수를 만드는 순간 바로 executor callback 함수로 인하여  Promise 안에 코드 블럭이 실행이된다.

     

    그래서 위 코드와 같이 각각 getApple() 와 getBanana()함수를 호출하여 Promise 객체를 생성해서, Promise가 바로 실행하게 한다.

     

    그리고 나서 await 키워드를 이용해서 각각 생성된 Promise type의 인스턴스 변수들을 동기화 시켜준다. 이렇게 실행하게 되면 각각의  코드가 병렬적으로 실행되어, Promise 객체 모두 동시에 1초의 지연 시간을 가지고 출력된다.

     

    하지만 위와 같이 복잡하게 코드를 작성할 필요는 없다.

     

     

     

    두번째

    useful Promise APIs를 활용한 방법

     

    promise의 메서드인 all 을 사용하면된다. all의 인자로 Promise 객체를 요소로 가지는 배열을 전달하게 되면, 모든 Promise 객체가 return 할 data를 준비할 때까지 병렬적으로 기다리게 된다.

     

    구체적인 예시로 위 와 같이 getApple()과 getBanana()를 요소로 가지는 배열을 인자로 all 메서드에 전달한다.

     

    all의 인자로 전달된 Promise객체의 들의 data 반환 준비가 끝나면, 반환된 결과들이 다시 배열로 전달이되어진다. 그리고 then 서드를 사용해서 그것을 가공할 수있다.

     

    * join() : JavaScript의 내장 메소드로, 배열을 string type으로 변환하여 묶어준다.

     

     

    세번째 

    어떤 것이든 상관 없이 제일 먼저 반환 준비가 완료된 과일 하나를 받아오고 싶다면,

     

     

    Promise 객체에 있는 race라는 내장 메소드를 사용하게 되면 인자로 전달된 배열중에 가장먼저 반환 준비가된 promise 객체의 반환 값만 전달이 되어진다.

     

    [출처-https://youtu.be/aoQSOZfz3vQ]

    '개발언어 > JavaScript' 카테고리의 다른 글

    JavaScript - 메서드와 this  (0) 2022.12.22
    JavaScript - 객체  (0) 2022.12.22
    Promise 개념부터 활용  (0) 2022.06.09
    비동기 처리의 시작 Callback 이해하기  (0) 2022.06.08
    JavaScript Closure  (0) 2022.04.03

    댓글

Designed by Tistory.