자바스크립트의 비동기 프로그래밍 방법

younoah·2021년 8월 14일
3

[My 자바스크립트]

목록 보기
6/17

자바스크립트의 동기 프로그래밍

function delay(sec, callback) {
  setTimeout(() => {
    callback(new Date().toISOString());
  }, sec * 1000);
}

// 동기
delay(1, result => {
  console.log(1, result);
});

delay(1, result => {
  console.log(2, result);
});

delay(1, result => {
  console.log(3, result);
});

// 출력
// (1초뒤 동시에 출력)
// 1
// 2
// 3

1초 뒤에 1, 2, 3이 동시에 출련된다.

자바스크립트는 기본적으로 동기적으로 동작한다. 콜백함수를 사용한다 해서 항상 비동기로 동작하는것이 아니다.

자바스크립트의 비동기를 제대로 이해하기 위해서는 이전에 작성한 자바스크립트의 비동기 동시성 프로그래밍 글을 참고하자.

자바스크립트의 비동기 프로그래밍

비동기 프로그래밍은 메인의 작업 흐름에서 특정 작업을 분리해서 새로운 작업 흐름을 만들어 병렬적으로 처리하는 방식이다.

콜백함수

function delay(sec, callback) {
  setTimeout(() => {
    callback(new Date().toISOString());
  }, sec * 1000);
}

delay(1, result => {
  console.log(1, result);

  delay(1, result => {
    console.log(2, result);

    delay(1, result => {
      console.log(3, result);
    });
  });
});

// 출력
// (1초의 간격을 두고 출력)
// 1
// 2
// 3

1초 뒤 1부터 1초의 간격으로 출력이 된다.

콜백에 콜백으로 구현하는 콜백지옥이 구현되는 이유는

위 코드에서 1 이라는 분리된 작업 뒤에 23 이라는 작업 흐름을 이어주기 위해서는 콜백에 콜백을 넘겨주는 식으로 구현할 수 밖에 없었기 때문이다.

콜백지옥을 벗어나기 위해 등장한 문법이

Promiseasync/await 이다.

Promiseasync/await 는 필요한 상황에 따라 선택하여 사용하면 된다.

프로미스

  • 프로미스는 비동기적인 작업의 상태와 값을 나타내는 객체이다.
  • 프로미스의 반환값은 프로미스이다.
  • 프로미스는 비동기 값을 일급으로 처리한다.
  • 프로미스는 상태(대기,성공,실패)를 값으로 사용할 수 있기 때문에 응용과 표현력이 좋다.
  • resolve, reject 으로 값을 갖는 프로미스를 리턴한다.
  • 값을 사용하기 위해서는 then, catch, finally 을 사용한다.
  • 예시1
function delayP(sec) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(new Date().toISOString());
    }, sec * 1000);
  });
}

delayP(1) //
  .then(res => {
    console.log(1, res);
    return delayP(1);
  })
  .then(res => {
    console.log(2, res);
    return delayP(1);
  })
  .then(res => {
    console.log(3, res);
    return delayP(1);
  })
  .finally(() => console.log('끝'));

// 출력
// (1초의 간격을 두고 출력)
// 1
// 2
// 3
// 끌

1초 뒤 1부터 1초의 간격으로 출력이 된다.

콜백으로 구현한 비동기 방식보다 훨씬 직관적이다.

  • 예시2
const getHen = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve('🐓'), 1000);
  });
};

const getEgg = hen => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${hen} => 🥚`), 1000);
  });
};

const cook = egg => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => 🍳`), 1000);
  });
};

getHen()
  .then(hen => getEgg(hen))
  .then(egg => cook(egg))
  .then(console.log)
  .finally(() => console.log('끝'));

// 출력
// 🐓 => 🥚 => 🍳
// 끝

각각의 비동기 작업(promise)를 then으로 하나의 작업흐름으로 만들기 때문에 간결하고 사용하기 쉽다.

async/await

  • async 는 함수의 리턴을 프로미스로 바꿔준다.

  • async 는 함수의 리턴값은 프로미스의 resolve와 동일하다.

  • async 함수의 리턴값이 then 의 인자로 절달된다.

  • awaitasync함수 내의 프로미스의 결과를 기다리게 한다. (비동기 로직을 기다린다.)

  • awaitasync함수 내의 일반함수에도 작성은 가능은 하다. (하지만 의미없는 행위이지 않나 싶다.)

function delayP(sec) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(new Date().toISOString());
    }, sec * 1000);
  });
}


async function asyncFunc() {
  const time = await delayP(3);

  return time;
}

asyncFunc().then(res => console.log('async 최종결과', res));

// 출력
// (3초뒤 아래 내용이 출력)
// async 최종결과 2021-08-14T14:00:50.295Z

어떤 함수내에서 비동기 작업의 값을 받아 와야할때 async/await 을 사용하면 유용하다.

promise, async/await 언제 사용할까?

  • 어떤 함수 자체가 비동기 작업인 경우 Promise 를 리턴하게 만든다.

  • 어떤 함수내에서 비동기 작업의 값을 받아 와야할때 async/await 을 사용한다.

  • Promise 를 리턴하는 함수, async/await 을 사용한 함수 모두 리턴값은 프로미스로 동일하므로 소비방식은 동일하다.

profile
console.log(noah(🍕 , 🍺)); // true

0개의 댓글