본문 바로가기
coding/javascript

Fetch API

by 코딩희송 2021. 10. 23.

들어가기

Fetch API를 이용하면 요청/응답과 같은 HTTP의 파이프라인을 구성하는 요소를 조작하는 것이 가능합니다.
또한 fetch()메서드를 이용하는 것으로 비동기 네트워크 통신을 쉽게 할 수 있게 도와줍니다.

Fetch의 기본스펙이 jQuery.ajax()와 다른 두가지:

1. fetch()로 부터 반환되는 프로미스 객체는 HTTP error 상태를 reject하지 않음.
(HTTP Status Code가 404 또는 500을 반환하더라도..! )
대신, ok상태가 false인 리졸브가 반환되며 네트워크 장애나 요청이 완료되지 못한 상태에는 reject가 반환됨.

2. 보통 쿠키를 보내거나 받지 않음. 쿠키를 전송하기 위해서는 자격증명 옵션을 반드시 설정해야함.
2017년 8월 25일 이후 기본 자격 정책이 same-origin으로 변경됨.

어케 사용함?

// fetch().then(){}.then(){}

fetch('http://example.com/movies.json').then((res) => {
 return res.json();
}).then((myJson) => {
  console.log(JSON.stringify(myJson));
})

요청에 옵션 주기

fetch() 메서드에 2번째 파라미터를 적용하는 것도 가능한데 초기 오브젝트를 이용해 다른 여러 세팅을 컨트롤 할 수 있다.

postData('http://example.com/answer', {answer: 42})
    .then(data => console.log(JSON.stringify(data)))
    .catch(error => console.error(error));

const postData = (url = '', data = {}) => {
    return fetch(url, {
        method: 'POST', // GET, POST, PUT, DELETE etc.
          mode: 'cors', // no-cors, cors, same-origin 
          cache: 'no-cache', // default, no-cache, reload, force-cache, only-if-cached
          credentials: 'same-origin', // include, same-origin, omit
          headers: {
            'Content-Type': 'application/json'
        },
      redirect: 'follow', // manual, follow, error
      referrer: 'no-referrer', // no-referrer, client
      body: JSON.stringfy(data)
    })
  .then(res => res.json())
}

fetch의 성공 여부 체크

성공적인 fetch()를 체크하는 정확한 방법은 프로미스 객체가 해결되었는지 체크하는 것이다.
그리고 Response.ok 프로퍼티가 true값을 가지고 있는지를 체크해봅니다.


var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

var myRequest = new Request('flowers.jpg', myInit);

fetch(myRequest).then((res)=>{
    if(res.ok) {
        return res.blob();
    }
  throw new Error('Network response was not ok.');
}).then((myData)=>{
  var objectURL = URL.creteObjectURL(myData);
  myImage.src = objectURL;
}).catch((err)=>{
    console.log(error.message)
})

Header

Header 인터페이스에서 Header()생성자를 이용해서 객체를 생성할 수 있다.
헤더 객체는 키-값으로 이루어진 멀티 맵으로 구성되어 있고,
똑같이 배열을 전달하거나 객체 리터럴을 생성자에 전달하는 방법도 있다.

var content = "something";
var myHeaders = new Headers();
myHeaders.append("Conent-Type", "text/plain");
myHeaders.append("Conent-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

// 또는

myHeaders = new Headers({
    "Content-Type": "text/plain",
      "Content-Length": content.length.toString(),
      "X-Custom-Header": "ProcessThisImmediately",
});

Header 값 확인하기

console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");

console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]

myHeaders.delete("X-Custom-Header");
console.log(myHeaders.getAll("X-Custom-Header")); // [ ]

에러 핸들링 처리

모든 Header메서드는 HTTP 헤더가 전달되지 않았을 경우 TypeError를 반환하는데, TypeError를 반환하지 않고 실패하는 경우도 있다.

var myResponse = Response.error();
try {
  myResponse.headers.set("Origin", "http://example.com");
} catch(e) {
  console.log("We havent't got JSON!");
}

헤더의 좋은 사용법으로는 처리하기전에 컨텐츠 타입으로 올바른지 타입체크를 하는 것이다.

fetch(myRequest).then((res) => {
    var contentType = res.headers.get('content-type');
      if(contentType && contentType.includes('application/json')) {
        return res.json();
    }
      throw new TypeError("Oops!");
})
.then(data => /* 코드 */)
.catch(error => /* 에러처리 */)

Response 객체

Response인스턴스들은 fetch() 프로미스가 resolve했을 때(=성공) 반환한다규!
아래는 어떤 Response 객체더라도 공통으로 사용되는 프로퍼티라능...

  • Response.status 〰〰 HTTP Status의 정수치, 기본값 200
  • Response.statusText 〰〰 HTTP Status 코드의 메서드와 일치하는 문자열, 기본값은 "OK"
  • Response.ok 〰〰 HTTP Status 코드가 200에서 299중 하나임을 체크하는 값, Boolean를 반환

Response객체는 동적으로 커스텀할 수도 있다.
이 방법은 서비스워커내에서 가능한 방법인데, 예를 들어 요청 데이터를 가져왔을 때 respondWith() 메서드에 의해 커스텀된 응답을 반환 시켜주는 경우다.

var myBody = new Blob();

addEventListener('fetch', (event)=> {
    event.respondWith(
        new Response(myBody, {
            headers: {'Cotent-Type': 'text/plain'}
        })
    );
});

Response()생성자는 2개의 파라미터 객체를 전달하는데,
첫번째는 Response Body, 두번째는 초기화 객체(= Request()의 클론을 생성하는 방법)이다.

Body

Request, Response 모두 Body를 갖고 있다능.
body는 아래 타입들 중 하나의 인스턴스를 갖고있다.

  • ArrayBuffer
  • ArrayBufferView (Unit8Array같은 타입된 배열)
  • Blob/File
  • 문자열
  • URLSearchParams
  • FormData

Body 믹스인은 요청/응답에 구현되어 콘텐츠를 추출하기 위해 아래 메서드가 정의되어 있다.
아래 메서드들로 최종적으로 요청으로 반환된 값을 내장하고 있는 promise를 반환한다.

  • arrayBuffer()
  • blob()
  • json()
  • text()
  • formData()

Request바디는 body 파라미터를 전달하는 것을 설정할 수 있다.

var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
    method: 'POST',
      body: form
})

요청과 응답은 Content-Type을 똑똑하게 결정하기 때문에 사전에 Content-Type 헤더를 설정하지 않아도 되는 경우 요처은 자동으로 설정해준다.

댓글