상권's

TIL 70 (async/await) 본문

~2022 작성 글/TIL

TIL 70 (async/await)

라마치 2022. 3. 19. 00:45

오늘은 ES8에서 도입된 async/await에 대해서 알아보겠습니다. 코드스테이츠 수강 당시에 async/await에 대해서 단순히 '프로미스를 동기적으로 처리할 수 있다.' 이렇게만 기억하고 사용했습니다. 사실 딱 저렇게 표현하는 게 정확한 거 같지만 조금 더 추가적으로 학습해보도록 하겠습니다.

 

async/await은 프로미스를 기반으로 동작합니다. async/await를 사용하면 프로미스의 then/catch/finally 후속 처리 메서드 없이 마치 동기 처리처럼 프로미스가 처리 결과를 반환하도록 구현할 수 있습니다.

 

await 키워드는 반드시 async 함수 내부에서 사용해야 합니다. async 키워를 사용해 async 함수를 정의하면 언제나 프로미스를 반환합니다. 명시적으로 프로미스를 반환하지 않는 async 함수도 암묵적으로 반환값을 resolve하는 프로미스를 반환합니다.

 

async 함수의 다음과 같이 사용할 수 있습니다.

async function foo(n) { return n; };
foo(1).then(v => console.log(v)); // 1

const bar = async fuction (n) { return n; };
bar(2).then(v => console.log(v)); // 2

const baz = async n => n;
baz(3).then(v => console.log(v)); // 3

 

await 키워드는 프로미스가 settled 상태가 될 때까지 대기하다가 settled 상태가 되면 프로미스가 resolve한 처리 결과를 반환합니다.

 

만약 여러 프로미스를 한 함수에서 실행 시킬 경우, 현재의 프로미스가 settled가 될 때까지 다음 실행을 일시 중지 시키기 때문에 사용에 유의해야합니다. 동시에 처리가 되어도 상관이 없는 프로미스일 경우에는 await Promise.all을 통하면 한 꺼번에 실행이 되면서 동기 처리가 가능합니다.

async function foo () {
  const testPromise1 = await new Promise(resolve => setTimeout(() => resolve(1), 3000));
  const testPromise2 = await new Promise(resolve => setTimeout(() => resolve(2), 2000));
  const testPromise3 = await new Promise(resolve => setTimeout(() => resolve(3), 1000));
  
  console.log([testPromise1, testPromise2, testPromise3]);
}

foo(); // 약 6초정도의 시간이 흐른 후 [1, 2, 3]이 출력되었습니다.


async function foo () {
  const result = await Promise.all([
    new Promise(resolve => setTimeout(() => resolve(3), 1000)),
    new Promise(resolve => setTimeout(() => resolve(1), 3000)),
    new Promise(resolve => setTimeout(() => resolve(2), 2000))
  ]);
  console.log(result);
}

foo(); // 약 3초의 시간이 흐른 후 출력됩니다.

위의 코드는 test1이 완료될 때까지 대기했다가 test2로 넘어가고, 다음 test3으로 진행되기 때문에 총 6초정도의 시간이 지나야 처리가 되지만, 아래의 코드의 경우에는 Promise.all로 처리하여서 가장 긴 3초의 시간이 흐른 후 출력이 될 수 있었습니다.

 

마지막으로 에러처리입니다. 앞서 북담 리팩토링을 할 때 try/catch로 코드를 구현했습니다. 코드스테이츠를 수강할 때 알았더라면 어땠을까라는 아쉬움이 있지만, 지금이라도 그때보다 성장한 것에 만족하고 이제는 다시 이런 아쉬움을 느끼지 않도록 노력하고 있습니다.

 

이렇게 저의 아쉬움을 남긴 에러 처리의 경우, async 함수 내에서 catch문을 사용해서 에러 처리를 하지 않으면, async 함수는 발생한 에러를 reject하는 프로미스로 반환합니다. 그래서 try/catch문을 사용하지 않고 then/catch로 에러를 캐치할 수 있습니다.

const foo = async () => {
  try {
    
  } catch {
    
  }
};

foo();


const foo = async () => {
  // 대충 await을 이용해 비동기를 동기처리
};

foo()
  .then(console.log)
  .catch(console.log)

 

이번에 학습하면서 async 함수와 promise.all-await, try/catch, async/await-then/catch 처리 등 다양하게 학습할 수 있었습니다. 서버를 구현하는 과정에서 오늘 학습했던 것을 이용할 수 있도록 지속적으로 복습하고 활용해보도록 하겠습니다.

'~2022 작성 글 > TIL' 카테고리의 다른 글

TIL 72 (클래스)  (0) 2022.03.22
TIL 71 (함수)  (0) 2022.03.21
TIL 68 (브라우저 렌더링 과정)  (0) 2022.03.15
TIL 67 (클로저)  (0) 2022.03.01
TIL 66 (렉시컬 환경)  (0) 2022.03.01
Comments