devlog,

프로미스와 제너레이터

FreeVue FreeVue Follow May 16, 2019 · 4 mins read
프로미스와 제너레이터
Share this

최근 우아한 테크러닝을 다니면서 리덕스와 리덕스 사가를 배웠습니다. 거기에서 비동기를 이용한 기능들을 많이 배웠는데 프로미스와 제너레이터를 이용하여 재미있는 기능구현을 배워 공유해보겠습니다.

function foo(fn) {
  fn(100)
}

foo(function(result) {
  console.log('콜백:', result) // 콜백: 100
})

아주 기본적인 자바스크립트 콜백방법입니다. 위 소스는 간단하지만 여러 비동기 작업을 하려면 콜백에 콜백에 콜백에… 늪에 빠집니다.

// 예시
foo(function() {
  bar(function() {
    fn1(function() {
      fn2(function() {
        // 이어서 계속...
      })
    })
  })
})

(자바스크립트의 HTML화)

function foo(fn) {
  return new Promise((resolve, reject) => {
    resolve(100)
    reject('Error!')
  })
}

foo()
  .then((result) => {
    console.log('프로미스(resolve):', result)
  })
  .catch((error) => {
    console.error('프로미스(reject)', error)
  })

콜백지옥에 안빠지려고 나온 프로미스 방법입니다. 프로미스로 함수를 생성하고 프로미스에서 지원해주는 then 메소드를 이용하여 then().then().then()… 체이닝으로 해결이 가능합니다.

resolve는 성공, reject는 실패시 나오는 함수입니다. 하지만 소스를 돌리면 foo() 함수의 프로미스는 성공 실패여부를 떠나서 resolve, reject를 전부 실행합니다.

// 예시
foo()
  .then((result) => {})
  .then((result) => {})
  .then((result) => {})
  .then((result) => {})
  .then((result) => {})
  .then((result) => {})
  .then((result) => {})
  .catch((error) => {})

(보기에는 좋아졌으나 소스의 양은 그대로이다.)

function foo() {
  return new Promise((resolve, reject) => {
    resolve(100)
    reject('Error!')
  })
}

async function bar() {
  try {
    const result = await foo()

    console.log('async-await:', result) // async-await: 100
  } catch (e) {
    console.error(e)
  }
}

bar()

함수앞에 async를 선언해주면 비동기 처리를 합니다. try에서 성공한 부분을 실행하고 await를 선언한 부분이 완료되면 아래의 소스들이 실행합니다.

// 예시
async function bar() {
  try {
    await foo()
    await fn1()
    await fn2()
  } catch (e) {}
}

(소스도 짧아지고 보기에도 이쁩니다.)

function* foo() {
  yield 10
  yield 20
  yield 30
  yield 40

  return 100
}

제너레이터는 함수선언에 * 를 같이 작성하시면 됩니다. 제너레이터는 실행할때마다 값을 반환합니다.

function* foo() {
  yield 10
  yield 20
  yield 30
  const res = yield 40

  console.log(res) // 제너레이터

  return 100
}

const bar = foo()

console.log(bar.next()) // { value: 10, done: false }
console.log(bar.next()) // { value: 20, done: false }
console.log(bar.next()) // { value: 30, done: false }
console.log(bar.next()) // { value: 40, done: false }
console.log(bar.next('제너레이터')) // { value: 100, done: true }

지원해주는 메소드인 next()를 실행할때마다 yield를 하나씩 실행합니다. 그리고 최종적으로 return을 반환하고 done부분을 true로 반환합니다.

next의 인자에 값을 넣으면 제너레이터 내부에서 값을 받을 수도 있습니다.