Javascript

자바스크립트의 비동기 처리

끈끈 2023. 5. 8. 00:27

 

자바스크립트 비동기 처리란?

 

특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성

 

필요한 이유?

 

서버로 데이터를 요청했을 때 언제 줄지 모르는 응답을 마냥 기다릴 수 없기 때문!

 

비동기 처리의 사례1
제이쿼리의 ajax

 

function getData() {
	var tableData;
	$.get('https://domain.com/products/1', function(response) {
		tableData = response;
	});
	return tableData;
}

console.log(getData()); // undefined

 

http get 요청으로 정보를 요청해 받아온 데이터가 response에 담겨 tableData라는 변수에 저장.

 

데이터가 올 때까지 기다리지 않고 return tableData를 실행하기 때문에 undefined가 출력되는 것.

 

비동기 처리의 사례2
setTimeout() : Web API의 한 종류

 

// #1
console.log('Hello');
// #2
setTimeout(function() {
	console.log('Bye');
}, 3000);
// #3
console.log('Hello Again');

 

#1 Hello 출력 → #2 실행 → #3 Hello Again 출력 → (#2 실행 3초 뒤) Bye 출력

 


 

비동기 처리 해결하기1
callback

 

데이터가 준비된 시점에만 동작을 수행하는 셈

 

function getData(callbackFunc) {
	$.get('https://domain.com/products/1', function(response) {
		callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
	});
}

getData(function(tableData) {
	console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});

 

but, 콜백 함수를 연속해서 사용할 때

 

콜백 안에 콜백을 계속 무는 형식인 콜백 지옥(Callback hell)이 발생할 수 있다.

 

가독성이 떨어지고 로직을 변경하기 어려움

 

콜백 지옥 해결을 위해 아래와 같이 각 콜백 함수를 분리해주는 방법이 있다

 

function parseValueDone(id) {
	auth(id, authDone);
}
function authDone(result) {
	display(result, displayDone);
}
function displayDone(text) {
	console.log(text);
}
$.get('url', function(response) {
	parseValue(response, parseValueDone);
});

 

비동기 처리 해결하기2
promise

 

위의 콜백 함수에 프로미스를 적용하면 아래와 같다

 

function getData(callback) {
  // new Promise() 추가
  return new Promise(function(resolve, reject) {
    $.get('url 주소/products/1', function(response) {
      // 데이터를 받으면 resolve() 호출
      resolve(response);
    });
  });
}

// getData()의 실행이 끝나면 호출되는 then()
getData().then(function(tableData) {
  // resolve()의 결과 값이 여기로 전달됨
  console.log(tableData); // $.get()의 reponse 값이 tableData에 전달됨
});

 

new Promise()

프로미스 생성. 콜백 함수의 인자는 resolve, reject

 

프로미스의 3가지 상태(states)

Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태

→ Fulfilled(이행=완료) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태

→ Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태

 

 

Fulfilled(이행) 상태

콜백 함수의 resolve 인자를 실행하면 then()을 이용하여 결과값을 받을 수 있다

 

then()으로 여러 개의 프로미스를 연결할 수 있다

 

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

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

 

Rejected(실패) 상태

콜백 함수의 reject 인자를 호출하면 실패 상태가 되어

 

catch()를 통해 실패한 이유(실패 처리의 결과값)를 받을 수 있다

 

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

// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function(err) {
  console.log(err); // Error: Request is failed
});

 

비동기 처리 해결하기3
promise + generator

 

비동기 처리 해결하기4
async & await

 

async function logName() {
  var user = await fetchUser('domain.com/users/1');
  if (user.id === 1) {
    console.log(user.name);
  }
}

 

서버에서 사용자 데이터를 불러와서 변수에 담고, 사용자 아이디가 1이면 사용자 이름을 출력.

 

기본 문법
→ 함수의 앞에 async라는 예약어를 붙인다
비동기 처리 메서드 앞에 await를 붙인다
프로미스 객체를 반환해야 await가 동작한다
→ await의 대상이 되는 비동기 처리 코드는 Axios 등 프로미스를 반환하는 API 호출 함수이다

async function 함수명() {
    await 비동기_처리_메서드_명();
}

 

예외 처리

async function 함수명() {
    try {
    } catch (error) {
    }
}

 

 


 

참고