Await vs Return vs Return Await

2020. 4. 6. 23:46Frontend

칼럼 await vs return vs return await를 정리한 글임을 서두에 밝힙니다.

 

 

 

 

 

 

 

 

자바스크립트를 사용하면서 처음에 가장 이해하기 어려웠던 부분중의 하나가 비동기 액션을 Async / Await과 Promise 객체를 사용하여 처리하는 것이었습니다. 이번 포스팅에서는 Async 함수의 결과를 Await, Return, Return Await 하는 경우에 각각 어떤 일들이 일어나는지를 확인해보겠습니다.

 

 

 

먼저 다음 Async 함수를 보도록 하겠습니다.

async function waitAndMaybeReject() {

    // Wait one second
    await new Promise(res => setTimeout(res, 1000));
    // Toss a coin
    const isHeads = Boolean(Math.round(Math.random());

    if (isHeads) return 'yay';
    throw Error('Boo!');
}

 

위 함수는 1초를 기다린 후에 Promise 객체를 반환합니다.

그리고 나서 50% 의 확률로 동전을 던져서 'yay'를 리턴하거나 Error를 리턴하도록 설계된 것임을 알 수 있습니다.

 

 

1초를 기다린 다음에 다음 액션들을 진행하도록 되어 있는 Async 함수이기 때문에, await 을 하지 않고 함수를 실행하면 Promise가 아직 Resolved 된 상태가 아니기 때문에 Pending 상태의 Promise 객체를 반환합니다.

 

반면, await을 사용하여 함수를 호출하게 되면, 실행 후 1초의 딜레이 시간 후에 50% 의 확률로 "yay"를 50%의 확률로 에러를 리턴합니다.

 

function 앞에 async를 붙이면 해당 함수는 항상 Promise 객체를 반환합니다. 명시적으로 Promise 객체를 반환하지 않는 경우, Promise객체가 아닌 것은 Promise로 변환한 뒤에 반환해줍니다.

 

waitAndMaybeReject()
-> Promise {<pending>}

await waitAndMaybeReject()
-> 50% "yay", 50% Error "boo"

 

 

 

Just Calling

async function foo() {

    // no await
    try {
        waitAndMaybeReject();
    } catch (e) {
        return 'caught';
    }
}

 

 

위의 foo() 함수는 waitAndMaybeReject() 함수를 호출하고 에러가 발생할 경우에는 'caught'을 리턴하도록 설계되어 있습니다. 하지만 waitAndMaybeReject()함수를 await 없이 그냥 호출했을 경우 waitAndMabeReject()함수의 결과는 그냥 Pending 상태의 Promise이고, 에러를 발생시키지 않았으므로 catch 문에도 걸리지 않아 return 할 값이 없는 상태가 됩니다. (Pending 상태의 Promise는 에러가 아니기 때문) 

 

 

하지만 foo()함수가 async 함수이기 때문에 Promise객체를 반환해야 하므로 Promise{<resolved>: undefined}를 반환하게 됩니다. 대개 이렇게 작성된 코드는 잘못 작성된 코드인 경우가 많습니다. waitAndMaybeReject()가 어떤 값을 가지고 있든지 상관없기 때문입니다.

 

 

 

 

Awaiting

async function foo() {

  try {
    await waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
  
}

 

foo()를 호출하면 waitAndMaybeReject()를 await 방식으로 호출합니다. 이렇게 되면, 위에서 살펴본 바와 같이 waitAndMaybeReject()함수가 50%의 확률로 "yay"를, 50%의 확률로 에러를 리턴할 것입니다.

 

"yay"를 리턴하는 경우, foo()함수는 마찬가지로 Promise를 리턴해야 하므로, undefined형태의 Promise를 리턴해줍니다. ("yay"라는 값을 foo에서 명시적으로 리턴해주기 때문에, foo()의 리턴값은 이 경우에 없는 것이나 마찬가지입니다.)

 

에러를 리턴하는 경우 catch문에 걸리게 되므로 'caught'으로 fullfilled 된 Promise가 리턴되게 됩니다. 

 

 

 

Returning

async function foo() {

  try {
    return waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
  
}

 

 

waitAndMaybeReject()함수는 await 구문 없이 실행되었을 경우 pending 상태의 Promise객체를 반환합니다. 이 값은 에러를 일으키지 않으므로 catch블록은 실행되지 않으며, 해당 Promise 객체가 그대로 리턴될 것입니다.

 

 

 

 Return - awaiting

async function foo() {

  try {
    return await waitAndMaybeReject();
  }
  catch (e) {
    return 'caught';
  }
  
}

 

위 함수는 상대적으로 이해하기가 쉽습니다.

awaiting 에서 살펴본 값을 foo가 결과값으로 리턴해주기 때문에 "yay"인 경우, "yay"로 fullfilled된 Promise 객체를, 에러가 걸린 경우, 'caught'으로 fullfilled된 Promise 객체를 리턴하게 됩니다.

 

 

반응형

'Frontend' 카테고리의 다른 글

[OAuth] OAuth 2.0  (0) 2020.07.04
JIT vs AOT 컴파일러  (1) 2020.06.16
[Crawler] Selenium으로 Everytime 크롤링하기  (1) 2020.05.10
HTTPS란  (0) 2020.05.05
CORS 란  (0) 2020.04.04