[JS] Callback, Promise, async & await

soor.dev·2021년 4월 25일
0

Java Script

목록 보기
26/26
post-thumbnail

Asynchronous

사용자가 어떤 요청을 했을 때, 그 반응을 기다리면서 다른 작업을 못한다면 어떨까? youtube에서 영상을 하나 틀었다고 생각하면, 우리는 그 영상이 로딩되는 동안 좋아요도 누를 수 있고, 댓글도 달 수 있고, 미니플레이어로 만들어 다른 영상을 검색할 수도 있다. 이렇게 어떠한 동작을 요청해 놓고, 다른 동작들도 요청할 수 있으며 먼저 완료된 동작을 스택에서 빼와서 실행해 주는 것이 Asynchronous : 비동기적 이라고 이해했다. (맞나..?) 비동기적으로 데이터가 처리되는 과정을 보려면 event loop에 대한 이해도 필요할 것이다.
비동기적으로 데이터를 처리하게 되면, 아래의 표우선 총 걸리는 시간이 아래처럼 현저히 줄어들게 될 것이다.


setTimeout 은 browser API라서 browser로 넘겨주고 callback queue에 보관했다가 설정한 시간 후에 출력


Callback

대표적인 비동기처리의 예시가 callback 함수이다.

지금 당장 실행하지 않지만 일정 시간 후에 로딩된 값을 전달해 주는 것이 콜백함수!

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

const printAll = () => {
  printString('JK', () => {
    printString('NJ', () => {
      printString('HEENI', () => {})
      // Callback hell의 조짐이 보임... 
    })
  })
}
printAll()  
// 'JK'
// 'NJ'
// 'HEENI' 순서대로 출력된다.
// printString의 인자로 콜백함수를 넣지 않았다면 랜덤하게 출력되었을 것이다.

  • synchronous callback
  • asynchronous callback

Promise

Promise 실행함수가 갖는 두 개의 파라미터

  • resolve() : 성공! 호출 시 프로미스를 이행
  • reject() : 실패! 호출 시 프로미스를 거부하여 오류를 발생시키고, 반환값을 무시

State

  • pending : 이행 또는 거부되지 않은 초기 상태
  • fulfilled : 프로미스를 이행함 (비동기 요청 완료) => .then()
  • rejected : 프로미스를 실패함(비동기 요청 실패) => .catch()

콜백대신 어떻게 비동기를 간편하게 처리할 수 있을까?

callback hell => promise!
promise hell => promise chaining!

// 이제 Promise를 사용하여 위의 콜백함수를 바꿔보자
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        console.log(string)
        resolve()
        },
      Math.floor(Math.random() * 100) + 1
    )
  })  
}

const printAll = () => {
  printString('JK')
  .then(() => {
    return printString('NJ') 
    // return을 적재적소에 사용해야 Promise Hell을 방지할 수 있음. 
    // return하지 않고 이어간다면 callback Hell과 비슷한 형태로 갈 수 있음.
  })
  .then(() => {
  	return printString('HEENI')	
  })
}
printAll()  

async & await

Promisesyntatic sugar
promise를 간결하고, 동기적으로 실행되는 것 처럼 보이게 한다.
일반 함수를 작성하는 것처럼 쓸 수 있다. 나중에 데이터를 불러올 때, 유용하게 쓸 수 있을 것 같다. 예를 들면, 데이터를 불러오는 작업을 끝내고 다음 작업을 이어가야 할 때? 쓰일 것 같다.

const first = () => {
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        console.log('내가 첫 번째!')
        resolve()
        },
      Math.floor(Math.random() * 100) + 1
    )
  })  
}
const second = () => {
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        console.log('나는 두 번째')
        resolve()
        },
      Math.floor(Math.random() * 100) + 1
    )
  })  
}
const third = () => {
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        console.log('나는 세 번째')
        resolve()
        },
      Math.floor(Math.random() * 100) + 1
    )
  })  
}
// async를 함수 앞에 쓰면 해당 코드블럭이 자동으로 promise로 바뀜!
// async & await 를 쓰지 않으면 랜덤으로 출력될 것이다.
const printAll =  async() => {
  const one = await first()
  console.log(one)
  const two = await second()
  console.log(two)
  const three = await third()
  console.log(three)
}

printAll()

// '나는 첫 번째'
// '나는 두 번째'
// '나는 세 번째'

0개의 댓글