[JavaScript] Async Await

Gomao·2023년 3월 26일
0

Web programming

목록 보기
7/16

비동기적 제어의 마지막 순서다.

Async Await?

자바스크립트에서 비동기 처리를 위해 "가장 최근에 나온" 문법이다.
여기서 마지막으로 한번 더 짚고 넘어갈 주제가 있다.

비동기 처리를 왜 해야 하는데?

JavaScript가 싱글 스레드 언어이기 때문이다.

Async Await 의 사용법

  1. function 앞에 async를 붙여서 사용한다.
  2. 비동기로 처리해야 하는 부분 앞에 await을 붙여서 사용한다.
  3. new Promise부분을 없애고 executor만 남긴다.
  4. resolve(value)부분을 return value로 변경한다.
  5. reject(new Error(...))부분을 throw new Error(...)로 변경한다.

★Promise를 완벽히 대체하지는 못한다!
다만, .then()으로 이어붙이던 부분을 await을 사용해서 처리할 수 있게 된다.

아직 잘 와닿지 않는다.

Promise 코드를 Async 코드로 변환하는 예시

Promise

const getTestcase = () => {
  let x = input1.value;
  let y = parseInt(input2.value);
  return new Promise((resolve, reject) => {
    if (y === 0) {
      reject();
    } else {
      resolve(solution(x, y));
    }
  });
};

Async

const getTestcase = async function () {
  let x = input1.value;
  let y = parseInt(input2.value);
  if (y === 0) {
    throw new Error();
  } else {
    return solution(x, y);
  }
};

사실 아직은 await을 사용하지 않아서 뭐가 좋다는 건지 잘 모르겠다.
그나마 가독성이 살짝 좋아졌다는 것 정도? 아니 익숙해졌다는 정도?

Await을 활용하는 방법

await은 반드시 async로 선언된 함수 내에서만 활용 가능하고,
이름 그대로 "기다리라"는 명령어로 작용한다.

아래와 같은 함수가 정의되어 있다고 생각하자.

function gomao(n){
	return new Promise((resolve) => setTimeout(resolve,n))
}

then으로만 작성

function go(){
	gomao(3)
    .then(() => gomao(3))
    .then(() => console.log("A")
    .then(() => console.log("B")
}

go()

await을 활용

async function mao(){
	await gomao(3)
    await gomao(3)
    console.log("A")
    console.log("B")
}

mao()

만약 이후에 추가적으로 뭔가 작업을 해줘야 하면 then을 이어붙일 수도 있고,
async 함수 내에서 오류를 처리해야 하는 경우에는 try/catch를 사용할 수 있다.
당장 내 예제를 만들기에는 이해가 조금 덜 되어 코드를 인용하겠다.

Async Await의 예외처리 방법 및 예제

const a = function(){
	return new Promise((resolve,reject) => {
    reject('go')
    })
}

이 함수와 같은 기능을 하는 async function을 하나 더 선언해준다.

async function b(){
	throw 'go'
}

함수를 인자로 받는 새로운 async function을 선언한다.

async function c(param) {
  try {
    await param;
  } catch (e) {
    console.log(e + "mao?");
  }
  console.log("gomao!");
}

실행할 코드

1. c();
2. c(a);
3. c(b);
4. c(a());
5. c(b());

각각 어떤 결과가 나오며 이유는 무엇일까?

1. c()

당연하게도, 아무런 인자도 받지 못했고 error도 발생하지 않았으므로
try문에서 아무것도 실행되지 않고, catch에도 아무것도 걸리지 않는다.
gomao!

2. c(a()) 혹은 c(b())

이번에는 잘 생각해봐야 한다.
이전과 달리 a() 혹은 b()가 실행되어 무언가 return된다. 
두 함수는 모두 error를 return 한다.
이제 function c에는 error가 전달되었다.
따라서, 이번에는 try/catch문이 실행될 것이다.
  1. try문을 들어가서 입력받은 a()가 실행되는 것을 기다린다.
  2. 실행된 a()"go"를 오류 인자로 catch문에 전달한다.
  3. catch문은 인자로 "go"를 받아, "mao?"를 붙여 출력한다.
  4. 따라서 "gomao?"가 출력된다.
  5. 이제 catch문이 끝나고, "gomao!"가 출력된다.

3. c(a) 혹은 c(b)

사실 말장난이다. a() 혹은 b()을 해야 error가 return되는 것이기 때문에,
아무 일도 일어나지 않는다. 
gomao!

그런데 왜 굳이 이걸 적었느냐고?
아래 함수를 한번 실행해보자.

(async function fn(){ 
  try{
    await b()
  }catch(e){
    console.log(e + "mao?")
  }
  console.log("gomao!")
})();

앞에 한 거랑 같은 결과가 나온다.

이때, 마지막 줄에 주목하자. })(); 바로 이부분.
매우 이상해보이지만, 함수를 선언하고 바로 실행하겠다는 뜻이다.
이번에는 await뒤에 이미 b()를 선언해둔 상태이다.
그러니까 async function c를 선언하고 또c(b()) 하기 귀찮다는 뜻이다.

만약 여기서 마지막 ()가 없다면?

함수를 정의만 하고 아무것도 실행하지 않은 상태인 것이다.
그래서 아무것도 안 나오는 것이다.

선언한 함수를 즉시 실행하기 위한 장치로 보면 되는것이다.

그럼 이걸로 Async/Await/try/catch 모든 것이 이해가 되었는가?

아니 솔직히 조금 부족한것 같음.ㅋㅋ
추가적인 학습 예제가 필요할 것으로 생각된다.

일단 오늘은 이정도에서 마무리 하는걸로..

profile
코딩꿈나무 고마오

0개의 댓글