JavaScript 17 비동기처리

김민호·2021년 12월 5일
0

JavaScript

목록 보기
17/21
post-thumbnail

동기식(Synchronous)

  • 작업의 직렬적 실행
  • 먼저 시작된 작업이 완전히 끝난 후에 다음 작업이 시작되는 방식이다
  • 모든 작업이 직렬로 배치되어 실행되어 있고 순차적으로 하나씩 진행된다
  • 때문에 블로킹(blocking) 문제가 발생하기도 한다

비동기식(Asynchronous)

  • 작업의 병렬적 실행
  • 작업이 하나씩 진행되는 것이 아니라, 동시다발적으로 작업을 실행한다
  • 나중에 시작해도 먼저 끝나는 작업이 있을 수 있다
  • 자바스크립트는 기본적으로 비동기적으로 동작한다

비동기 처리

  • 특정 로직의 실행이 끝날 때까지 기다려주지 않고 나머지 코드를 먼저 실행하는 것

Javascript 는 Single Thread 이다.

이벤트를 처리하는 call stack이 하나 뿐인 언어이기 때문에 여러가지 이벤트를 처리할 때에 동기적으로 처리하게 된다면 하나의 이벤트가 모두 처리될 때까지 기다렸다가 다른 업무를 수행하게 되는 현상이 발생한다.
그래서 JS는 즉시 처리하지 못하는 이벤트들을 Web API로 보내 콜스택이 비었을 때 먼저 처리된 이벤트들을 줄 세워 다시 이벤트 큐에 정렬시켜 놓는다
Web API로 들어오는 순서는 중요하지 않고, 어떤 이벤트가 먼저 처리되느냐가 중요하다. 즉 순서가 확실하지 않은 비동기 처리인 것이다.
하지만 비동기 처리 이벤트들의 순서가 중요해질 경우는 어떻게 해야할까?
이렇게 순차적으로 진행되어야 하는 비동기를 처리하는 3가지 방식이 있다.

비동기 처리 3가지 방식

JS에는 다음의 3가지 비동기 처리 방식이 있다.

1. 콜백 함수 사용
2. Promise
3. Promise를 활용한 async/await

1. 콜백 함수 사용

개념

어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하는 함수

예시

// #1
console.log('1');
// #2
setTimeout(function() {
	console.log('2');
}, 2000);
// #3
console.log('3');

이렇게 찍어보면

  • '1' 출력
  • 2초 있다가 '2' 출력
  • '3' 출력

이렇게 출력된다고 생각할 수 있지만, 비동기 방식으로 실행되는 setTimeout() 에 의해 다음과 같은 순서로 출력된다.

  • '1' 출력
  • '3' 출력
  • 2초 있다가 '2' 출력

문제점

  • 콜백 함수를 중첩해서 사용하게 되면 계속해서 코드를 들여쓰기 해야하고 그러다보면 코드 가독성이 현저하게 떨어지게 되기 때문에 콜백 함수를 인자로 넘겨서 비동기 처리를 하는 스타일을 피하는 추세
  • 콜백 지옥에 빠지는 경우가 흔하고 이를 해결하기 위해 Promise나 async/await를 이용하는 방법들로 대체

2. Promise

개념

  • 비동기 처리에 사용되는 자바스크립트 내장 객체로 다음과 같은 3가지 상태가 있다

대기(pending): 이행하거나 거부되지 않은 초기 상태
Settled: 결과 값이 성공 혹은 실패로 반환된 상태
이행(fulfilled): 연산이 성공적으로 완료됨
거부(rejected): 연산이 실패함

  • 상태 값은 크게 Pending과 Settled로 나눌 수 있으며, Settled은 다시 fulfilled와 Rejected로 나누어 진다.
  • 한번 Setteld된 값은 재실행 할 수 없다.

promise 사용법

new Promise(function(resolve, reject) {
  // ...
});
  • new Promise() 객체를 생성하여 콜백 함수를 선언할 수 있는데 이때의 인자는 resolve, reject를 사용한다
  • resolve는 결과가 성공인 Promise 객체를 반환하고 reject는 결과가 실패인 Promise 객체를 반환한다.
  • 반환된 Promise 객체를 처리할 때 성공 시 then을 사용하고 실패 시 catch를 사용하여 처리한다.

let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout(function(){
// 성공 시 resolve 사용
    resolve(`Minho`)
  }, 3000);
});

// 성공 시 then 사용하여 결과 처리
myFirstPromise.then((successMessage) => {
  console.log(`Hi! ` + successMessage);
});




let mySecondPromise = new Promise((resolve, reject) => {
  setTimeout(function(){
// 성공 시 resolve 사용
    reject(`No Way!`)
  }, 3000);
});

// 성공 시 then 사용하여 결과 처리
mySecondPromise.catch((failMessage) => {
  console.log(`OMG! ` + failMessage);
});

정리
다 이해할 순 없지만
resolve.then 은 성공했을 경우,
reject.catch는 실패했을 경우 사용한다는 것만 잡고 넘어가자

promise 의 장점

  • promise를 사용하면 콜백지옥에서 벗어날 수 있다
function a() {
  return new Promise({
    // ...
  });
}

function b() {
  return new Promise({
    // ...
  });
}

function c() {
  return new Promise({
    // ...
  });
}

myFirstPromise()
.then(a)
.then(b)
.then(c);
  • 콜백 함수를 사용했으면 훨씬 길어지고 복잡해졌을 코드도 위 예시와 같이 Promise 객체를 반환하면 여러 개의 then을 연결하여 간단히 처리할 수 있다

3. async / await

async 개념

  • async / await는 promise를 기반으로 한 개념이다
  • 더 좋은 점은 resolve, reject, then, catch를 쓰지 않고 기본 메소드 앞에 async만 붙이면 반환되는 값이 Promise 객체가 된다

await 개념

  • await 은 async 가 붙은 메소드에서만 사용할 수 있다.

성공 실패 처리 방법

promise에서 then, catch로 성공 실패를 처리해준 것처럼 여기서도 처리해주어야 한다

  • 성공
async function hello() {
  return 'HIHIHIHIHIHIHIHI';
}

async function callHello(){
  try {
    let gutentag = await hello();
    console.log('Success!!!');
} catch (e) {
    console.log('Failure!!!!!!!');
  }
}

callHello();
# 'Success!!!'
  • 실패
async function hello() {
  throw new Error('Fail~~~~');
}

async function callHello(){
  try {
    let gutentag = await hello();
    console.log('Success!!!');
} catch (e) {
    console.log(e.message);
  }
}

callHello();
# 'Fail~~~~'

참고
https://www.daleseo.com/js-async-callback/
https://velog.io/@wkahd01/%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC
https://velog.io/@change/JavaScript-asyncawait%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C

profile
개발자로서의 삶은 https://velog.io/@maxminos 에서 기록하고 있습니다 😀

0개의 댓글