[Web] JavaScript - 비동기 프로그래밍

당고짱·2022년 8월 10일
0

Web study

목록 보기
9/11
post-thumbnail

동기와 비동기

동기 : 현재 실행 중인 테스크가 종료될 때 까지 다음 테스크가 대기하는 방식

  • 장점 : 순서가 보장된다. 흐름을 예측하기 쉽다.
  • 단점 : 동시에 여러 작업을 수행할 수 없다.

비동기 : 현재 실행 중인 테스크가 종료되지 않았더라도 다음 테스크를 바로 실행하는 방식

  • 장점 : 동시에 여러 작업을 수행할 수 있다.
  • 단점 : 소스 코드의 순서를 보장하지 않는다. 흐름을 예측하기 어렵다.

setTimeout

setTimeout(기다린 후 실행시킬 함수(콜백함수), 기다릴 ms, 콜백함수에 넣을 추가 인자)

  • 비동기 함수
  • 인자로 들어온 콜백 함수를 예약하기만 하고 바로 끝난다.
  • 아무 일도 하지 않고 단순히 기다리기만 하는 함수
  • setTimeout에 의해 기다리는 동작은 본래의 코드 흐름과는 상관 없이 독립적으로 돌아간다.

콜백지옥(callback hell)

함수의 매개 변수로 넘겨지는 콜백 함수가 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상

step1(function (value1) {
    step2(function (value2) {
        step3(function (value3) {
            step4(function (value4) {
                step5(function (value5) {
                    step6(function (value6) {
                        // Do something with value6
                    });
                });
            });
        });
    });
});

함수를 호출할 때 비동기 작업이 시작되며, 함수 호출 시점에 다음 작업(콜백 함수)도 넘겨준다. 이와 같은 현상이 많이 반복되면 콜백지옥에 빠지게 된다.


Promise

비동기 작업을 좀 더 편하게 할 수 있도록 ES6에서 도입한 객체로 콜백지옥의 단점을 보완한다.

const promise = new Promise((resolve, reject) => {
	resolve();
});
promise
	.then(() => {
		console.log("성공");
	})
    .catch(() => {
    	console.log("실패");
    });
// 성공
  • Promise는 생성자 함수이다.
  • 생성자는 (resolve, reject)를 하나의 인자로 받는다. (executor 함수)
    • reselve : 비동기 작업이 성공했을 때 사용하는 함수
    • reject : 비동기 작업이 실패했을 때 사용하는 함수
  • 비동기 작업이 성공하거나 실패했을 때 후속처리를 하기 위한 함수
    • then : Promise가 성공했을 때의 동작을 지정
    • catch : Promise가 실패했을 때의 동작을 지정

Promise 예제

function startAsync(age) {
return new Promise((resolve, reject) => {
  if (age > 20) resolve();
    else reject();
});
}

setTimeout(() => {
const promise1 = startAsync(25);

promise1
  .then(() => {
    console.log("1 then!");
  })
  .catch(() => {
    console.log("1 catch!");
  });

const promise2 = startAsync(15);

promise2
  .then(() => {
    console.log("2.then!");
  })
  .catch(() => {
    console.log("2 catch!");
  });
}, 1000);

// 1 then!
// 2 catch!

Promise 3가지 상태

  • pending(대기): 비동기 처리 로직이 완료되지 않은 상태
  • fulfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환한 상태
  • rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태

pending

new Promise()

Promise 메서드를 호출하면 pending 상태가 된다. 이 때 콜백함수를 선언할 수 있고, 콜백함수의 인자는 resolve, reject이다.

fulfilled

new Promise(function(resolve, reject){
	resolve();
});

resolve를 실행하면 이행 상태가 된다.

function getData(){
  return new Promise(function(resolve, reject){
    var data = 100;
    resolve(data);
  });
};

// resolve()의 결과 값 data를 resolveData로 받음
getData().then(function(resolvedData){
  console.log(resolvedData); // 100
})

이행 상태가 되면 then()으로 결과 값을 받을 수 있다.

Rejected

new Promise(function(resolve, reject) => {
  reject();
})

reject를 실행하면 실패 상태가 된다.

function getData(){
  new Promise(function(resolve, reject){
    reject(new Error("Request is failed"));
  })
}

getData()
  .then()
  .catch(function(err){
    console.log(err); // Error: Reqeust is failed
  })

실패 상태가 되면 catch()로 결과 값을 받을 수 있다.


async/await

  • async: 비동기 작업을 만드는 손쉬운 방법
  • await: Promise가 끝날 때 까지 기다리도록 만드는 방법
function setTimeoutPromise(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(), ms);
  });
}

async function startAsync(age) {
  if (age > 20) return `${age} success`;
  else throw new Error(`${age} is not over 20`);
}

async function startAsyncJobs() {
  await setTimeoutPromise(1000);
  const promise1 = startAsync(25);
  try {
    const value = await promise1;
    console.log(value);
  } catch (e) {
    console.error(e);
  }
  const promise2 = startAsync(15);
  try {
    const value = await promise2;
    console.log(value);
  } catch (e) {
    console.error(e);
  }
}

startAsyncJobs();
  • async는 무조건 Promise를 반환한다.
  • Promise를 쉽게 사용하기 위해 ES8에 도입했다.
  • Promise의 콜백 지옥 단점을 보완한다.
  • 소스 코드의 흐름이 동기적으로 보인다.

Ajax(Asynchronous JavaScript and XML)

클라이언트와 서버간에 XML 데이터를 주고 받는 기술

  • 자바스크립트 라이브러리 중 하나
  • XMLHttpRequest 객체를 이용해 전체 페이지를 새로 고치지 않고 페이지의 일부만 로드하는 기법
  • 자바스크립트를 이용한 비동기 통신 기법(Promise 사용)

Ajax를 사용하는 이유

  • 단순히 웹에서 무언가 부르거나 데이터를 조회하고 싶을 때, 페이지 전체를 새로고침 하지 않기 위해 사용한다.
  • Http 페이지 전체가 아닌 일부만 갱신 가능하도록 XMLHttpRequest 객체를 통해 서버에 요청한다. 이 때 필요한 데이터만 받이 갱신하기 때문에 시간과 자원을 아낄 수 있다.

장점

  • 웹페이지 속도 향상
  • 서버의 처리가 완료 될 때까지 기다리지 않고 처리 가능
  • 서버에서 Data만 전송하면 되므로 코드가 간결해진다.
  • 기존 웹에서는 불가능했던 다양한 UI를 가능하게 해준다.

단점

  • 히스토리 관리가 안된다.
  • 보안에 신경써야 한다.
  • 연속적으로 데이터를 요청하면 서버 부하가 증가할 수 있다.
  • Cross-Domain 문제(다른 도메인과 통신이 불가능)가 발생한다.

fetch API

XMLHttpRequest보다 더 발전된 API

fetch(url, options)
  .then((response) => console.log("response:", response))
  .catch((error) => console.log("error:", error));
  • 첫 번째 인자는 url, 두 번째 인자는 options 객체를 받는다.
  • Promise 객체를 반환한다.
  • JSON의 타입별로 쉽게 적용이 가능하다.

axios

가장 널리 쓰이는 http 통신 라이브러리

axios({
    method: "get", // 통신 방식
    url: "www.naver.com", // 서버
})
.then(function(response) {
  console.log(response.data)
  console.log(response.status)
  console.log(response.statusText)
  console.log(response.headers)
  console.log(response.config)
})
  • Vue/React 권고 라이브러리로 지정되어 있다.
  • Promise 객체를 반환한다.
  • 사용하기 편리하다.

▶ fetch와 axios의 자세한 내용은 이 곳 참고 ◀

profile
초심 잃지 말기 🙂

0개의 댓글