[TIL -비동기통신]

..·2023년 4월 29일
0

TIL

목록 보기
19/22
post-thumbnail

Axios

  • Promise를 기초로해서 http통신을 할 수 있는 클라이언트 라이브러리다.

yarn add axios

yarn add json-server

import "./App.css";
import { useEffect, useState } from "react";
import axios from "axios";

function App() {
  const [todos, setTodos] = useState(null);
  const [inputValue, setInputValue] = useState({ title: "" });
  const [targetId, setTargetId] = useState("");
  const [contents, setContents] = useState("");
  //조회 함수
  const fetchTodos = async () => {
    const { data } = await axios.get("http://localhost:4000/todos");
    // console.log("data", data);
    setTodos(data);
  };

  // 추가 함수
  const onSubmitHanlder = async () => {
    axios.post("http://localhost:4000/todos", inputValue);
    setTodos([...todos, inputValue]);
    fetchTodos();
  };

  //삭제 함수
  const onDeleteButtonHandler = async (id) => {
    axios.delete(`http://localhost:4000/todos/${id}`);
    setTodos(
      todos.filter((item) => {
        return item.id !== id;
      })
    );
  };
  // 수정 함수
  const onUpdateButtonHandler = async () => {
    axios.patch(`http://localhost:4000/todos/${targetId}`, {
      title: contents,
    });
    setTodos(
      todos.map((item) => {
        if (item.id == targetId) {
          return { ...item, title: contents };
        } else {
          return item;
        }
      })
    );
  };

  useEffect(() => {
    fetchTodos();
    //db로부터 값을 가져올 것이다.
  }, []);

  return (
    <>
      <div>
        {/* 수정 영역 */}
        <input
          type="text"
          placeholder="수정할 아이디"
          value={targetId}
          onChange={(e) => {
            setTargetId(e.target.value);
          }}
        />
        <input
          type="text"
          placeholder="수정할 내용"
          value={contents}
          onChange={(e) => {
            setContents(e.target.value);
          }}
        />
        <button onClick={onUpdateButtonHandler}>수정</button>
        <br />
        <br />
      </div>
      <div>
        {/* input 영역 */}
        <form
          onSubmit={(e) => {
            e.preventDefault();
            //디폴트 기능을 막아서 form 고유특성인 새로고침을 막는다

            // 버튼 클릭시 input에 들어있는 값(state)를 이용하여 DB에 저장(POST 요청)
            onSubmitHanlder();
          }}
        >
          <input
            type="text"
            value={inputValue.title}
            onChange={(e) => {
              setInputValue({
                title: e.target.value,
              });
            }}
          />
          <button>추가</button>
        </form>
      </div>
      <div>
        {/* 데이터 영역 */}
        {todos?.map((item) => {
          //옵셔널 체이닝
          return (
            <div key={item.id}>
              {item.id} : {item.title}
              &nbsp;
              <button onClick={() => onDeleteButtonHandler(item.id)}>
                삭제
              </button>
            </div>
          );
        })}
      </div>
    </>
  );
}
export default App;

Fetch

  • Fetchsms ES6 부터 도입된 자바스크립트 내장 라이브러리이다.
  • Promise 기반 비동기 통신 라이브러리.
  • axios처럼 데이터를 다루기 쉽고 내장 라이브러리이기 때문에 별도의 설치와 import를 필요로 하지 않는다.
  • 하지만 fetch에는 단점이 존재한다.

fetch의 단점

  • 미지원 브라우저 존재
  • 개발자에게 불친절한 response
  • axios에 비해 부족한 기능

fetch 와 axios 비교

CASE 1. 데이터 읽어오기

  1. fetch

    const url = "https://jsonplaceholder.typicode.com/todos";
    
    fetch(url)
    .then((response) => response.json())
    .then(console.log);
    • fetch().then을 한 상태여도 여전히 JSON 포맷의 응답이 아니기 때문에 response.json()을 한번 더 해주는 과정이 필요하다.
    • 따라서, fetch로 데이터를 요청하는 경우 두 개의 .then()이 필요하다.
  2. axios

    const url = "https://jsonplaceholder.typicode.com/todos";
    
    axios.get(url).then((response) => console.log(response.data));
    • axios는 응답(response)을 기본적으로 JSON 포맷으로 제공한다. 단순히 response.data로만 사용하면 된다.

CASE 2. 에러 처리

  1. axios

    const url = "https://jsonplaceholder.typicode.com/todos";
    
    axios
      .get(url)
      .then((response) => console.log(response.data))
      .catch((err) => {
        console.log(err.message);
      });
    • axios.get()요청이 반환하는 Promise 객체가 갖고있는 상태코드가 2xx의 범위를 넘어가면 거부(reject)를 한다.
    • 따라서, 곧바로 catch() 부분을 통해 error handling이 가능하다.
      const url = "https://jsonplaceholder.typicode.com/todos";
      
      // axios 요청 로직
      axios
        .get(url)
        .then((response) => console.log(response.data))
      	.catch((err) => {
      
      		// 오류 객체 내의 response가 존재한다 = 서버가 오류 응답을 주었다	
      		if (err.response) {
      			
      	    const { status, config } = err.response;
      	
      			// 없는 페이지
      	    if (status === 404) {
      	      console.log(`${config.url} not found`);
      	    }
      
      			// 서버 오류
      	    if (status === 500) {
      	      console.log("Server error");
      	    }
      	
      		// 요청이 이루어졌으나 서버에서 응답이 없었을 경우
      	  } else if (err.request) {
      	    console.log("Error", err.message);
      		// 그 외 다른 에러
      	  } else {
      	    console.log("Error", err.message);
      	  }
      	});
  2. fetch

    const url = "https://jsonplaceholder.typicode.com/todos";
    
    fetch(url)
      .then((response) => {
        if (!response.ok) {
          throw new Error(
            `This is an HTTP error: The status is ${response.status}`
          );
        }
        return response.json();
      })
      .then(console.log)
      .catch((err) => {
        console.log(err.message);
      });

    fetch의 경우, catch()가 발생하는 경우는 오직 네트워크 장애 케이스이다. 따라서 개발자가 일일히 then() 안에 모든 케이스에 대한 HTTP 에러 처리를 해야한다.

0개의 댓글