상세 컨텐츠

본문 제목

서버에서 Promise와 fetch로 데이터 불러오기 (실무편)

IT 공부/프론트엔드(Front-end)

by 듀_77 2021. 12. 13. 08:54

본문

반응형

 

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(alert); // 프라미스 전체가 처리되면 1, 2, 3이 반환됩니다. 각 프라미스는 배열을 구성하는 요소가 됩니다.

Promise.all

여러가지 promise를 한꺼번에 실행시켜준다.

하나라도 거부되면 에러가 나면서

전체를 거절한다.

(모 아니면 도인 상황일 때 유용하다.)

 

ex) 여러 개의 url에 동시에 request를 보내고,

download가 모두 완료되고 나서 

contents를 처리할 때 사용 

 

코드해석

 

Promise 전체가 처리되고 나서 (3초 이후에)

1, 2, 3이 반환된다.

 

→ result: 배열 [1, 2, 3]이 반환된다.

 

let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/remy',
  'https://api.github.com/users/jeresig'
];

// fetch를 사용해 url을 프라미스로 매핑합니다.
let requests = urls.map(url => fetch(url));

// Promise.all은 모든 작업이 이행될 때까지 기다립니다.
Promise.all(requests)
  .then(responses => responses.forEach(
    response => alert(`${response.url}: ${response.status}`)
  ));

배열에 url담겨 있을때, fetch로 처리하기

작업해야할 데이터인 url들을 promise로 매핑한다.

그리고 해당 배열을 Promise.all로 다시 감싼다.

 

let names = ['iliakan', 'remy', 'jeresig'];

let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));

Promise.all(requests)
  .then(responses => {
    // 모든 응답이 성공적으로 이행되었습니다.
    for(let response of responses) {
      alert(`${response.url}: ${response.status}`); // 모든 url의 응답코드가 200입니다.
    }

    return responses;
  })
  // 응답 메시지가 담긴 배열을 response.json()로 매핑해, 내용을 읽습니다.
  .then(responses => Promise.all(responses.map(r => r.json())))
  // JSON 형태의 응답 메시지는 파싱 되어 배열 'users'에 저장됩니다.
  .then(users => users.forEach(user => alert(user.name)));

Github 유저네임 배열로, 사용자 정보 가져오기

(= id를 기준점으로 장바구니 목록 가져올 때도 사용)

 

 

Promise.all([
  fetch('/template.html'),
  fetch('/style.css'),
  fetch('/data.json')
]).then(render); // render 메서드는 fetch 결과 전부가 있어야 제대로 동작합니다.

Promise.allSettled

스펙에 추가된지 얼마 안되어서,

올세틀드를 쓰려면!

IE같은 옛날 브라우저들은 

pollyfill 처리를 해주어야 한다.

(pollyfill: 개발할 때, 해당 기능을 제공하지 않는

웹 브라우저 상의 기능을 따로 구현해주는 코드)

 

- 모든 프로미스가 처리될 때까지 기다린다

- 보통 allSettled를 많이 쓴다(노드에서)

fetch를 이용해서 여러 사람의 정보를 불러올 때!

여러 request 중, 하나가 실패하더라도

다른 request들의 결과는 남아 있어야 한다.

 

그래서 Promise.allSettled를 사용한다.

결과

이런 식으로 결과값을 받을 수 있다.

 

Promise.all과 Promise.allSettled 모두

결과값(=object)을 담은 배열을 반환한다.

 

차이점: 

'올'은 하나라도 실패되면 거부된다.

'올 세틀드'는 모든 promise가 처리될때까지 기다려준다.

 

*

모던자바스크립트 튜토리얼로 간단하게 

Promise API 중에 중요한 개념인

Promise.all과 Promise.allSettled를 알아보았다.

 

//프라미스 API 정리

(데이터 불러올 때 혼용해서 사용,

아래 실무에서 Promise 사용하는 법을 읽어보고

같이 응용해보면 좋다.)

 

 

실무에서 언제 프로미스를 사용할까?

Node.js에서는 계속 사용하지만,

노드가 아닌 상황에서는 보통 다음과 같이 쓴다.

 

fetch('https://raw.githubusercontent.com/paullabkorea/coronaVaccinationStatus/main/data/data.json')
    .then(function(response) {
        return response.json();
    })
    .then(function(json) {
        console.log(json);
        return json
    })
console.log(1);
console.log(2);

실제 실무에서 쓰는 코드 

fetch는 지금 promise로 호출하고 있다. (github url 부분)

실행이 되면, then

또 실행이 되면 then을 호출하는 식이다.

 

그리고 return값으로

response.js를 전달하고,

성공했으므로 다음 then 구문에 전달해준다.

 

(여기서 console.log로 json data를 확인한다.)

 

*지금 fetch가 promise방식이기 때문에

then/ then을 활용해서 catch나 finally도 활용할 수 있다.

 

 

결과화면 창

프론트엔드에서 데이터를 불러오는 방법은

크게 2가지가 있다.

 

만약 전국의 1차 접종 퍼센트를 알고 싶다면?

이런 식으로 전체 데이터를 불러와서

일부를 추출할 수 있다.

 

1. data.js 파일 만들어서 연결하기

변수를 선언해서 data 배열을 집어넣은 후

원본 파일과 연결하는 방법이 있다.

 

2. 위 코드와 같이

fetch와 promise를 사용해서 데이터 연결하기(권장)

 

이 데이터는 서버에서 실시간으로 받아오는 것.

서버에서 들어오는 값은 변경이 된다.

 

그래서 data.js 파일로 저장한 데이터는 쓸 수가 없다.

서버에서 실시간으로 받아오는 

데이터를 쓰기 위해 위 방법을 쓴다.

 

반응형

 

fetch와 Promise의 상속 구조는 어떻게 될까?

console에 

fetch와 Promise를 찍어보았다.

 

prototype을 보니, 둘 다 object를 할당받고 있다.

같은 object를 상속받는 듯 한데,

좀 더 찾아봐야할 것 같다.

 

// 모던자바스크립트 예제
let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

setTimeout을 쓴 이유

위 코드는 promise도 비동기고,

setTimeout도 비동기이기 때문에

굳이 셋타임아웃을 쓸 필요가 없다.

 

→ 네트워크에서 1초동안 지연된다는 것을

보여주려고 사용했다.

(실시간으로 데이터를 받아올 때 현상)

 

fetch('https://raw.githubusercontent.com/paullabkorea/coronaVaccinationStatus/main/data/data.json')
    .then(function(response) {
        return response.json();
    })
    .then(function(json) {
        console.log(json);
        return json
    })
console.log(1);
console.log(2);

console.log(1)과 (2)를 찍어준 이유

이 코드에서도 fetch구문에서

데이터를 받아오려면 시간이 걸린다.

 

그래서 console.log (1), (2)를 먼저 

출력해서 데이터를 받아와준다.

 

 

fetch의 data를 보면 완전한

json 형태이다.

(앞에 변수 선언해서 사용하지 않는다)

 

data.js 파일 형태로 저장해서,

데이터를 불러오려면 변수명이 필요했다.

(get을 전역변수처럼 사용한 것)

그런데 fetch로 데이터를 받아오면,

변수 선언해줄 필요가 없다.

(실시간으로 갖고 오는 데이터)

 

fetch('https://raw.githubusercontent.com/paullabkorea/coronaVaccinationStatus/main/data/data.json')
    .then(function(response) {
        console.log(1);
        return response.json();
    })
    .then(function(json) {
        console.log(2);
        console.log(json);
        return json
    })
    .then(function(json) {
        console.log(3);
        console.log(json.filter(s => s['시·도별(1)'] === '전국'));
        return
    })

깃허브 데이터에서 '전국 1차 접종 퍼센트' 데이터만 꺼내오기

(예제)

- filter와 map 쓰기 / for문이나 while문 사용가능

 

1. '전국' 데이터만 가져오기

filter로 ['시 도별 (1)'] === '전국' 객체를 가지고 왔음 
(시도별이 전국인 객체를 가져왔음)

// 1차 접종 퍼센트를 구해주세요!
fetch('https://raw.githubusercontent.com/paullabkorea/coronaVaccinationStatus/main/data/data.json')
    .then(function(response) {
        console.log(1);
        return response.json();
    })
    .then(function(json) {
        console.log(2);
        console.log(json);
        return json
    })
    .then(function(json) {
        console.log(3);
        console.log(json.filter(s => s['시·도별(1)'] === '전국').map(obj => obj['1차 접종 퍼센트']));
        return
    })

 

2. "1차 접종 퍼센트" 데이터 가져오기

filter로 '전국'이라는 객체를 가져왔고,

- map으로 (obj라는 오브젝트가 들어오게 되면, 
"1차 접종 퍼센트'' 데이터를 꺼낸다)

 

이 code에 for문을 같이 쓰면 응용해서

DDOS 공격을 할 수 있다.

 

→ 수업시간에 100명 정도 되는 인원이 예제 코드를 쳤더니

Promise <pending> 상태에 머물러 버린다.

(깃허브로부터 ddos 공격으로 인지되어

차단당한것)

 

fetch('https://raw.githubusercontent.com/paullabkorea/coronaVaccinationStatus/main/data/data.json')
    .then(function(response) {
        console.log(1);
        throw Error('애러났어유!')
        return response.json();
    })
    .then(function(json) {
        console.log(2);
        console.log(json);
        return json
    })
    .then(function(json) {
        console.log(3);
        console.log(json.filter(s => s['시·도별(1)'] === '전국'));
        return
    })
    .catch(err => alert(err))

3. 에러났을 때 CODE

(데이터 못 받아왔을 때)

(=error가 던져지면 catch로 받을 수 있다.)

 

출처: 제주코딩베이스캠프 강의, 모던자바스크립트 튜토리얼

https://ko.javascript.info/promise-api

 

프라미스 API

 

ko.javascript.info

반응형

관련글 더보기

댓글 영역