studye / typescript

타입스크립트는 자바스크립트랑 다른 언어인가요?
7 stars 0 forks source link

[Chapter 4] async and await #16

Open casiru opened 7 years ago

casiru commented 7 years ago

then 을 보내며..

처음 Promise를 접했을 때의 맘 속의 생각은 oh! 였지만, 사용하면서 든 생각은 hm? 이었다.

Promise는 아래 사항들에 대해 분명 유익하지만, 어떻게 callback hell에 대한 구원투수가 되는지는 의문이었다.

pure한 함수들을 chain으로 연결하여 깔끔하게 나타낼 수 있지만,

function iAmPure() {
}

function iAmPureToo() {

}

start()
  .then(iAmPure)
  .then(iAmPureToo)
  .catch(error => ())

깔끔한게 항상 읽고 수정하기 좋은 코드는 아니며, 더 중요한 점은 코드를 작성하다 보면, pure하지 않는 함수들이 생성되기 마련이다. (그것도 아주 많이) default

결국 아래와 같은 코드가 만들어 진다.

let a, b;
start().then((res) => {
    a = res
    return fetch().then((res) => {
        b = a + res
        return fetch().then((res) => {
            return a * b + res
        })
    })
}).catch(error => {})

중간 중간 발생할 수 있는 error를 한방에 잡았다는 점에, Promise에 감탄하며 박수를 치고 싶지만, 저 코드를 보다 보면 그런 맘이 싹 사라진다.

나의 바램은 그저 이렇다 기획 변경으로 API 하나를 더 불러야 되는데, 코드에 대한 죄책감 없이 5분만에 끝내고 싶다

그러기 위해 다른 무언가가 더 필요했다...

Async and await

await

await의 쓰임은 간단하다. Promise가 끝나기를 기다렸다가 Promise의 결과를 반환 받을 수 있다.

function fetch() {
  return new Promise(.....)
}

const result = await fetch()

마치 저 fetch가 끝날 때 까지 App이 멈출것 같지만, 비동기적으로 수행 된다는 점이 좋다. 하지만 await는 막 사용 할 수가 없다. async 함수 내에서만 사용 가능 하다.

async

사용법은 아래와 같다.

async fetchAll( ) {
  await fetchA()
  await fetchB()
  await fetchC()
  ....
}

const result = await fetchAll()

async 함수의 구현 부분은 await를 사용한다는 점을 제외하고는 일반 함수와 동일하다. 그리고 async 함수는 Promise를 반환하는 함수와 동일하게 사용 할 수 있다.

아래의 방법이 모두 가능하다.

fetch().then( ... )

await fetch()

Promise.all[fetch(), fetch(), ...].then( ... )

await [fetch(), fetch(), ...]

Error handling

await 로 호출하는 함수에서 발생하는 Error는 try catch로 잡을 수 있다.

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url); 
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

동작 방식은 예상하는 그 방식과 동일하다.

예상보다 못한 박수

await의 등장은 비동기 프로그래밍로 인한 scope을 가진 무언가에게는 환영 받을 일이다. 그리고 대게 이런 무언가는 전통적인 controller 일 가능성이 크다.

얘들은 비동기 동작의 결과에 집착해 그 결과를 기다린다. (callback / then / await 를 통해..) 그리고 기다림이 끝나면 또 뭔가를 하기 바쁘다. 그래서 예쁘게(?) 작업을 수행하려면 예쁘게 기다리고 싶다.

function renderItems(items) {}

async function controller() {
    const list = await fetch('/list')
    const items = await [
        fetch('/item?id=' + list[0].id),
        fetch('/item?id=' + list[1].id),    
    ];

    renderItems(items)
}

이 동작을 callback으로 했다면, 생각만 해도 끔찍하다. (물론 더 예쁘게 할 수 있지만, 위에서 말했듯이 난 5분 밖에 없다..;)

하지만 비동기 동작을 수행 후의 동작이 simple 하다면?

fetch('/api', (res) => {
   updateSomething(res);
   //끝!
})

call의 결과가 어찌되든 관심 없고, 그냥 나는 call() 만 하면 된다면?

doAction(); // action 수행 후 처리는 그에 연관된 다른 component가 알아서 할거야

어떻게 기다리냐는 코드 품질에 큰 영향을 주지 않을 것이다.

언제 부터인가 이런 기다림 없는 미학의 방법론과 구현체들이 Web Application에서 많이 사용 되고 있어, Client 개발용으로 await 가 정말정말 반갑느냐에 대해서 확실히 답을 못하겠다.

하지만 nodejs 의 인기를 상승 시킬 만한 중요한 요소가 되기를 기대해 본다.

async / await 는 nodejs 8 부터 flag 없이 사용 가능