JavaScript - 비동기처리방식, fetch, promise

isk·2022년 11월 6일

JavaScript

목록 보기
22/39

자바스크립트는 기본적으로 동기 방식의 언어다.
위에서부터 아래로 코드가 실행되지만, 서버통신 같은 코드들은 비동기 방식이다.

동기처리는, 요청 - 결과가 동시에 일어나므로, 요청에 대한 결과가 있기 전까지 다음 요청을 실행하지 않는다.
비동기처리는, 요청 - 결과가 동시에 일어나지 않으므로, 요정에 대한 결과가 없어도 다른 요청을 실행한다.

비동기처리 방식에는 문제점이 존재한다.
서버와 통신을 주고 받은 데이터를 처리해야 하는데,
통신을 주고 받는 사이 아래처럼 다른 코드를 실행시켜 순서가 뒤죽박죽이 될 수도 있다.

function getData() {
	let data;
	$.get('https://google.com/1', function(response) {
		data = response;
	});
	return data;
}

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

특정 url에 데이터를 요청하고, 요청에 대한 응답을 response에 저장하며, data라는 변수에 response를 담는다.
그리고 data를 return한다. 결과값이 나오기 전에 콘솔창에 찍어버리니 undefined가 출력된다.

이런 문제를 해결하기 위해, 실행순서를 보장 받기 위해 콜백함수를 사용한다.

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

getData(function(data) { // 익명함수사용. getData의 인자값으로 익명함수가 들어가며, 익명함수의 인자값으로 date가 들어감
	console.log(data); // $.get()의 response 값이 data에 전달됨
});

콜백함수를 사용하면 이렇다.

왜 콜백함수를 사용하면 비동기처리방식의 문제점을 해결할 수 있는지 생각해봤다.

  • 내가 내린 결론 -

console.log를 마지막에 찍고 싶은데 자꾸 중간에 찍히는 상황일 때,
'console.log를 가진 함수'를 '다른 함수' 어딘가에 넣게 되면 (콜백함수)
'console.log를 가진 함수'의 console.log는 그 위치에서만 실행.
(함수는 실행을 시켜줘야 동작하기 때문에 비동기처리의 동작 방식에서 예외(?)가 된다.)


fetch를 사용해서 url을 얻는데, fetch는 서버에 데이터를 요청하는 것이며, 비동기처리방식이다.

function callback () {
	console.log("a");
}

fetch('html').than(callback);

console.log(1);
console.log(2);

// 1
// 2
// a

fetch로 요청한 데이터를 가져오는 작업이 완료된 이후에 then의 인자에 들어가있는 함수가 실행되는데,
fetch는 비동기처리이기 때문에 than 요청에 대한 응답을 처리하는 사이에 console.log를 실행한다.

데이터를 가져오는 작업에 많은 시간이 소요될 수 있는데, than을 사용해서 그 시간동안 다른 행동을 취할 수 있게 해준다.

fetch('html').then((response) => console.log(response));

than에 삽입된 함수의 첫번째 인자는 response 객체를 가지면서 호출한다. (인자의 이름은 아무거나 써도 되지만 보통 response)

콘솔창에 response을 찍어보면 response 객체의 여러 속성값이 나온다.

fetch('html').then((response) => {
	if(response.status == '404') {
    	alert('찾을 수 없음');
    }
});

response의 속성값들 중 status를 가지고, 찾는 데이터가 없을 경우 경고창을 띄우는 등을 할 수 있다.


fetch를 사용할 때, 데이터를 바로 사용할 수는 없다. 단계를 거쳐야 사용할 수 있다.

fetch("html").then((response) => response.json()).then(json) => console.log(json)
// 또는
fetch("html")
.then((response) => response.json())
.then(json) => console.log(json)

첫 번째 인자는 response로 받고, 그걸 json형태로 parsing(파싱)한다. (parsing : 구문분석, 해석)

파싱한 json을 가지고 콘솔창에 찍거나, 다른 것들을 할 수 있다.

fetch("코인 url")
.then((response) => response.json())
.then((json) => setCoins(json));

json으로 파싱한 데이터를 state에 담아서 사용할 수도 있다.

더 나아가 정보를 받아올 때, 다 받아오지도 않았는데 빈 화면을 띄우거나 오류를 뿜는 경우가 있다.

이런 경우 promise를 사용하여 예방할 수 있다.

function getData() {
  return new Promise(function(resolve, reject) {
    $.get('url', function(response) {
      if (response) {
        resolve(response);
      }
      reject(new Error("error!"));
    });
  });
}

기본뼈대다.

promise의 콜백함수 인자로 resolve, reject가 오는데, 각각 성공과 실패 시 사용할 수 있다.


function getData() {
  return new Promise(function(resolve, reject) {
    $.get('url', function(response) {
      if (response) {
        resolve(response);
      }
      reject(new Error("error!"));
    });
  });
}

getData().then(function(data) {
  console.log(data); // response 값
}).catch(function(error) {
  console.error(error); // Error
});

성공했을 경우 then을 사용하여 data를 받아올 수 있고, 실패했을 경우 catch를 사용하여 에러 창을 띄울 수 있다.

0개의 댓글