비동기 javascript를 동기식으로 만들기

y0ung·2021년 1월 13일
0

JavaScript

목록 보기
14/20
post-thumbnail

자바스크립트는 싱글 스레드 프로그래밍 언어이기 때문에 비동기 처리가 필수 적이다. 비동기 처리는 그 결과가 언제 반환될지 알수 없기 때문에 동기식으로 처리하는 기법들이 사용되어야 한다. 대표적으로 setTimeout이 있고, callbackpromise가 있다. 세 가지 모두 비동기 코드를 동기식으로 작성하는데 풀륭한 기법들이지만, 모두 약간의 문제점을 가지고 있다. 하지만 async & await는 이런 문제를 해결함과 동시에 그 사용법에서 있어서도 훨씬 단순해졌다.

setTimeout

특정 시간 동안 기다렸다가 이후 첫번째 파라미터의 함수를 실행하는 방식이다.

let first = 10,
    second = 20,
    result = 0

function add(x,y){
  return x + y
}

setTimeout(()=>{
  result = add(first,second)
  console.log(result) // 40
},1000);

first = 20;

30이 아닌 40이 찍힐까?

자바스크립트는 각각의 task를 큐에 적재해두고 순서대로 처리한다. 최초의 task는 스크립트 파일 자체 이다. 이 첫번째 task내에 setTimeout은 별도의 task를 생성하고 첫번째 task가 종료되길 기다린다. 첫번째 task인 스크립트의 실행이 끝나면 비로소 setTimeout의 함수를 실행할 준비를 한다. 즉 first의 값은 초기에 10이였지만 첫번째 스크립트가 종료되면 20이 되기 때문에 결과적으로 result = 40이 된다.

이코드를 동기식으로 처리하려면 어떻게 해야하지??

let first = 10,
    second = 20,
    result = 0

function add(x,y){
  return x + y
}

function getResult(callback){
  setTimeout(()=>{
    result = add(first,second)
    console.log(result) // 30
    
    callback() // 콜백함수를 이용한다.
  },1000);
}

getResult(()=>{
  first = 20;
})

위와 같이 callback함수를 사용하면 비동기 코드를 동기식으로 작성할수 있다.

callback

callback 함수란 호출하는 함수가 호출되는 함수로 전달하는 함수를 말하며 이때 callback 함수의 제어권은 호출되는 함수에게 있다. callback 함수는 setTimeout함수와 같은 비동기 코드를 동기식으로 처리하기 위해 사용된다.

callback이 직관적이고 이해가 어렵지는 않지만, 여러개의 callback을 연달아 사용하게 되면 에러가 발생할 가능성이 높고, 코드의 가독성도 떨어지게된다.

function goWork(time1, timeStartWork) {
  wakeUp(time1, function (time2) {
    takeSubway(time2, function(time3) {
      takeOffSubway(time3, function(time4) {
        arriveWork(time4, function(arrivalTime) {
          if (arrivalTime > timeStartWork) {
            fire();
          }
        }
      }
    }
  }
}

callback은 비동기 코드를 동기적으로 만드는데 확실한 방법이긴 하지만 남발하게 되면 가독성이 크게 떨어지고 코드의 복잡성도 크게 증가하게 된다. 또한 callback의 호출에 대한 제어권이 다른 함수들에게 넘어가 버리기 때문에 각 콜백함수가 언제 어떻게 몇번 실행되는지 확신 할 수 없다.

promise

어떤 작업이 성공했을 때(resolve), promise객체의 then()함수에 넘겨진 파라미터를 단 한번만 호출하겠다는 약속이다. callback의 경우 제어권이 호출되는 함수로 넘어가 버리기 때문에 신뢰성이 다소 떨어지지만 promise는 함수 실행이 성공했을때 then() 함수이 파라미터가 단 한번만 호출되기 때문에 함수를 호출하는 입장에서 확신을 가지고 코드를 작성할수 있다.
또한 실패 했을 경우 (reject)에도 catch()함수를 통해서 실패 이후의 작업을 처리할 수 있다.

function goWork(time1, timeStartWork) {
  return wakeUp(time1)
    .then(time2 => tackSubway(time2))
    .then(time3 => takeOffSubway(time3))
    .then(time4 => arriveWork(time4))
    .then(arrivalTime => {
      if (arrivalTime > timeStartWork) {
        fire()
      }
    })
}

callback보다는 훨씬 가독성이 높아졌다.

async & await

function 키워드 앞에 async만 붙여주면 되고 , 비동기로 처리되는 부분 앞에 await만 붙여주면 된다. 다만, 몇 가지 주의 점이 있다면 await 뒷부분은 반드시 promise를 반환해야 한다는 것과 async function 자체도 promise를 반환한다는 것이다.

async function goWork(time1, timeStartWork) {
  const time2 = await wakeUp(time1)
  const time3 = await takeSubway(time2)
  const time4 = await takeOffSubway(time3)
  const arrivalTime = await arriveWork(time4)
  if (arrivalTime > timeStartWork) {
    fire()
  }
}

훨씬더 직관적인 코드이다.


참고
https://blueshw.github.io/2018/02/27/async-await/

profile
어제보다는 오늘 더 나은

0개의 댓글