Asynchronous(1)

안정태·2021년 4월 24일
0

Study

목록 보기
10/33

Asynchronous

Synchronous : 동기적인 처리, 요청을 받고 작업을 처리하는 동안 다른 요청을 멈춘다.
Asynchronous : 비동기적인 처리, 요청을 받으면서 작업을 처리

위 사진에서 보면 동기적인처리는 하나의 작업이 끝나야지 다음 작업을 실행하기 때문에 시간이 걸리는 반면 비동기는 하나의 작업과 동시에 다른 작업을 실행하기 때문에 시간적인 측면에서 효율적으로 활용 가능하다.

만약, 우리가 유튜브를 본다고 했을 때, 인터넷 상황이 안 좋으면 로딩이 길다. 그 말은 즉, 영상을 가져오기까지 오랜 시간이 걸린다는 것이다. 하지만 영상이 로딩 되는 동안 다른 작업을 할 수 없다면 어떨까? 매우 불편할 것이다.

유튜브 처럼 영상이 로딩 되는동안 다른 영상을 틀거나 다른 작업을 할 수 있는 것을 비동기라고 한다.

Callback

비동기 작업에서 순서를 제어하고 싶으면 어떻게 해야할까?

const printString = (string) => {
  setTimeout(
    () => {
      console.log(string)
    },
    Math.floor(Math.random()*100)+1
    )
}

const printAll = () => {
  printString("A")
  printString("B")
  printString("C")
}
printAll() // What do you expect?

위 코드의 printString함수는 랜덤한 시간을 받은 후 랜덤하게 문자열을 출력하는 함수이다. 그렇다면 그 밑에 printAll함수를 실행하면 어떻게 될까요? 아마 무작위 순서로 A, B, C가 출력될 것 입니다.

const printString = (string, callback) => {
  setTimeout(
    () => {
      console.log(string)
      callback()
    },
    Math.floor(Math.random()*100)+1
    )
}

const printAll = () => {
  printString("A", () => {
    printString("B", () => {
      printString("C", () => {})
    })
  })
}
printAll() // now what do you expect?

그렇다면 이 함수의 결과는 어떻게 나올까요? A, B, C 는 순서대로 출력될 것 입니다. 그렇다면 왜 이 함수는 순서대로 출력 될까요. 이유는 callback함수를 인자를 줌으로 console.log(string)을 실행한 뒤 callback함수를 실행 하기 때문입니다.
이 처럼 callback을 통해서 우리는 함수의 비동기 작업의 순서를 제어 할 수 있게 된다.

//Callback error handling Design
const somethingGonnaHappen = callback => {
  waitingUntilSomethingHappens()
  
  if(isSomethingGood){
    callback(null, something)
  }
  if(isSomethingBad){
    callback(something, null)
  }
}

//Usage
somethingGonnaHappen((err,data) => {
  if(err){
    console.log('ERR!!');
    return;
  }
  return data;
})

callback이 이렇게 고마운 친구지만 계속해서 사용한다면 코드가 계속 밀려들아가면서 작성 될 것이다. 이를 해결해 주는 것이 바로 promise이다.

Promise

new Promise() <promis는 객체다>
resolve() : Go to Next Action
reject() : Handle Error

Promise는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

//Callback -> Promise
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        console.log(string)
        resolve()
      },
      Math.floor(Math.random()*100) + 1
    )
  })
}

const printAll = () => {
  printString("A")
  .then(() => {
    return printString("B") //메서드 체인을 위해서 리턴해줘야 한다.
  })
  .then(() => {
    return printString("C")
  })
}
printAll()

위 코드는 A, B, C를 출력하는 callback함수를 Promise로 나타낸 것이다. callback에 비해서 가독성이 좋고 코드가 훨씬 깔끔해 졌다.

Promise는 첫 함수를 실행하고 다음 실행 함수를 .then()으로 넘겨준다. callback은 에러 핸들링을 매번 처리해줘야 하는 것과 다르게 promise.catch()를 통해서 어디서 에러가 나도 잡아낼 수 있다.

Promise는 다음 3가지 특징을 보장한다.

  • 콜백은 현재 실행중인 콜 스택을 완료하기 전에 절대 호출되지 않는다.
  • 비동기 작업이 성공하거나 실패한 뒤에 .then()을 이용하여 추가한 콜백의 경우에도 위와 같다.
  • .then()을 여러번 사용하여 여러개의 콜백을 추가할 수 있다. 그리고 각각 순서대로 실행된다.

Promise의 가장 큰 장점은 chaining이다.

async, await

const result = async () => {
  const one = await gotoCodestates();
  console.log(one)
  
  const two = await sitAndCode();
  console.log(two)
  
  const three = await eatLunch();
  console.log(three)
  
  const four = await goToBed();
  console.log(four)

위 코드는 비동기적으로 실행이 되기는 하지만, 코드 자체가 동기적인 모양으로 작성이 되서 훨씬 가독성이 좋아진다.

profile
코딩하는 펭귄

0개의 댓글