멋쟁이v의 개발일지

[Javascript] 비동기통신(fetch, axios, ajax) 본문

0년차/Javascript

[Javascript] 비동기통신(fetch, axios, ajax)

멋쟁이v 2023. 8. 19. 16:12
728x90
320x100


01. 동기/비동기 통신

💡
node.js에서는 동기(synchronous)와 비동기(asynchronous)를 구분할 수 있다.

동기

➡️ 순서대로 처리한다.

➡️ 프로세스 이후의 요청에 대해서 업데이트 된 상황을 유지하기 위함.

➡️ 요청을 보낸 후 해당 요청의 응답을 받아야 다음 동작을 실행하는 방식이다.

비동기

➡️ 프로세스 이전의 상황이 어떻게 결론이 나든 상관없이 동시에 요청을 처리하는 방식이다.

➡️ 요청을 보낸 후 응답과 관계없이 다음 동작을 실행하는 방식이다.

02. fetch

  • fetch API
    💡
    내장 라이브러리이기 때문에 import 없이 사용 가능하다.

    ➡️ XMLHttpRequest 대체자로 나온것이 fetch API이다.

    • 비동기 http 요청을 좀 더 쓰기 편하게 해준다.

    ➡️ Promise 기반으로 동작한다. (콜백지옥 탈출)

    ➡️ 기본 응답 결과는 Response 객체이다.

    • json으로 바꾸거나 text로 바꾸는 처리 과정이 필요하다.

    👉🏻
    Promise

    ➡️ 자바스크립트 비동기 처리에 사용되는 객체이다.

    ➡️ 3가지 상태(states)

    • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태 → new Promise();
    • Fulfilled(이행) : 비동기 처리가 완료되어 promise가 결과 값을 반환해준 상태 → resolve();
    • Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태 → reject();

    ➡️ Promise((resolve, reject) ⇒ { … })

    • resolve : 주어진 값으로 이행하는 Promise 객체를 반환한다.
    • reject : 주어진 사유로 거부하는 Promise 객체를 반환한다.

    ➡️ Promise.prototype.then

    • promise에 이행과 거부 처리시 콜백을 추가한다.
    • resovle(data) → then(function (data) { … });
    • reject(new Error(’ ’)) → then().catch(function(err) {…});
    • Promise 예제
      let myFirstPromise = new Promise((resolve, reject) => {
        // 우리가 수행한 비동기 작업이 성공한 경우 resolve(...)를 호출하고, 실패한 경우 reject(...)를 호출합니다.
        // 이 예제에서는 setTimeout()을 사용해 비동기 코드를 흉내냅니다.
        // 실제로는 여기서 XHR이나 HTML5 API를 사용할 것입니다.
        setTimeout( function() {
          resolve("성공!")
        }, 250)
      })
      
      myFirstPromise.then((successMessage) => {
        // successMessage는 위에서 resolve(...) 호출에 제공한 값입니다.
        // 문자열이어야 하는 법은 없지만, 위에서 문자열을 줬으니 아마 문자열일 것입니다.
        console.log("와! " + successMessage) // 와! 성공!
      });

    👉🏻
    fetch

    ➡️ 서버에 네트워크 요청을 보내고 새로운 정보를 받아오는 일을 수행한다.

    ➡️ HTTP response 객체를 래핑한 Promise 객체를 반환한다.

    • then을 사용하여 resolve한 객체를 전달받을 수 있다.

    ➡️ fetch() : let promise = fetch(url, [option]);

    • option에 아무것도 넘기지 않으면 요청은 GET 메서드로 진행된다.

    ➡️ 응답시 단계

    • 1단계 : 서버에서 응답헤더를 받자마자 fetch호출 시 반환되는 promise가 내장 클래스 Response의 인스턴스와 함께 이행된다.
    • 2단계 : 추가 메서드를 호출해 응답 본문을 받는다.

    ➡️ GET 요청방식 (단순히 원격 API에 있는 데이터를 가져올 때)

    • fetch(”url”)

      .then((response) ⇒ response.json())

      .then((data) ⇒ … );

      response 객체는 json 메서드를 제공하고, 이 메서드를 호출하면 response 객체로부터 JSON 형태의 데이터를 자바스크립트 객체로 변환하여 얻을 수 있다.

    • fetch 예제
      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title>비동기통신</title>
          <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
                integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
          <script src="http://code.jquery.com/jquery-latest.min.js"></script>
          <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
                  integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
                  crossorigin="anonymous"></script>
      </head>
      <body>
      <h1>비동기통신</h1>
      
      <br><br>
      <h2>fetch</h2>
      - 서버에 네트워크 요청을 보내고 새로운 정보를 받아오는 일을 수행<br>
      - fetch() : let promise = fetch(url, [option]);<br>
      - option에 아무것도 넘기지 않으면 요청은 GET 메서드로 진행됨<br>
      - 응답시 단계<br>
      - 1단계 : 서버에서 응답헤더를 받자마자 fetch호출 시 반환되는 promese가
      내장 클래스 Response의 인스턴스와 함께 이행<br>
      - (아직 본문(body) 도착하기 전 상태, 개발자는 응답 헤더를 보고 요청이
      성공적으로 처리되었는지 아닌지 확인)<br>
      - (http 상태는 응답 프로퍼티를 사용해 확인
      status: http상태코드, ok: 불린값 http상태코드가 200~299사이일 경우 true)<br>
      - 2단계 : 추가 메서드를 호출해 응답 본문을 받음<br>
      - response.text() : 응답을 읽고 텍스트 반환<br>
      - response.json() : 응답을 JSON 형태로 파싱<br>
      - response.formData() : 응답을 FormData 객체 형태로 반환<br>
      - response.blob() : 응답을 Blob(타입이 있는 바이너리 데이터)형태로 반환<br>
      - response.arrayBuffer() : 응답을 ArrayBuffer(바이너리 데이터를 로우레벨 형식으로 표현한것) 형태로 반환<br>
      
      <div class="container-fluid mt-5 ml-5">
          <div class="row">
              <div class="card">
                  <div class="card-header">회원정보</div>
                  <div class="card-body">
                      <form>
                          <div class="form-row">
                              <div class="form-group col-md-6">
                                  <label for="memberId">회원 아이디</label>
                                  <input type="text" class="form-control" id="memberId">
                              </div>
                              <div class="form-group col-md-6">
                                  <label for="memberPw">회원 비밀번호</label>
                                  <input type="password" class="form-control" id="memberPw">
                              </div>
                          </div>
                          <div class="form-row">
                              <div class="form-group col-md-6">
                                  <label for="memberName">회원 이름</label>
                                  <input type="text" class="form-control" id="memberName">
                              </div>
                              <div class="form-group col-md-6">
                                  <label for="memberEmail">회원 이메일</label>
                                  <input type="email" class="form-control" id="memberEmail">
                              </div>
                          </div>
                          <div class="form-group">
                              <label for="memberAddr">회원 주소</label>
                              <input type="text" class="form-control" id="memberAddr">
                          </div>
                          <div class="form-group text-right">
                              <button type="button" id="exAjax1" class="btn btn-primary">ajax 통신1</button>
                              <button type="button" id="exAjax2" class="btn btn-primary">ajax 통신2</button>
                          </div>
                      </form>
                  </div>
              </div>
          </div>
      </div>
      
      <script type="text/javascript">
          const request = {
              get(url) {
                  url = encodeURIComponent(url);
                  return fetch(url);
              },
              post(url, payload) {
                  url = encodeURIComponent(url);
                  return fetch(url, {
                      method: 'POST',
                      headers: {'content-Type': 'application/json'},
                      body: JSON.stringify(payload)
                  });
              }
          }
          const $exAjax1 = document.querySelector('#exAjax1');
          $exAjax1.addEventListener('click', function () {
              console.log(request.get('./24_비동기통신_fetch_ex.json'));
      
              request.get('./24_비동기통신_fetch_ex.json')
                  .then(response => response.json())
                  .then(function (memberInfo) {
                      console.log(memberInfo, '<---ajax요청후 응답받은 json객체');
                      const memberId = document.querySelector('#memberId');
                      const memberPw = document.querySelector('#memberPw');
                      const memberName = document.querySelector('#memberName');
                      const memberEmail = document.querySelector('#memberEmail');
                      const memberAddr = document.querySelector('#memberAddr');
                      memberId.value = memberInfo.memberId;
                      memberPw.value = memberInfo.memberPw;
                      memberName.value = memberInfo.memberName;
                      memberEmail.value = memberInfo.memberEmail;
                      memberAddr.value = memberInfo.memberAddr;
                  });
      
          });
      
          // promise를 리턴하는 함수
          // async, await
      
          async function ajaxRequest() {
              let response = await request.get('./24_비동기통신_fetch_ex.json');
              console.log(response);
              let resultData = await response.json();
              console.log(resultData);
              return resultData;
          }
      
          const $exAjax2 = document.querySelector('#exAjax2');
          $exAjax2.addEventListener('click', function () {
              ajaxRequest()
                  .then(result => console.log(result, '<----'));
          });
      
      </script>
      </body>
      </html>

    🗣
    async와 await

    ➡️ async를 사용하면 promise를 리턴하는 함수로 만들어준다.

    ➡️ 사용법

    • function 앞에 async를 붙여준다.
    • promise 앞에 await를 붙여준다.
    • async가 붙은 함수는 promise 객체를 반환하므로 then 메서드를 사용 가능하다.

03. axios

  • axios
    💡
    브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리이다. (라이브러리 설치 필요)

    ➡️ 자동으로 JSON데이터 형식으로 변환된다.

    ➡️ 문법: axios({ 옵션 }) or axios.get('url', {옵션}), axios.post('url', {옵션})

    ➡️ method : 요청방식(기본값:get)

    ➡️ url: 서버주소

    ➡️ data: 요청시 쿼리파라미터 ex: data: { '키' : 값 , '키' : 값 ...}

    ➡️ responseType : 서버가 응답해주는 데이터의 타입 지정 (arraybuffer, document, json(기본값), text, stream, blob)

    • axios 예제
      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title>비동기통신</title>
          <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
          <script src="http://code.jquery.com/jquery-latest.min.js"></script>
          <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
          <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
          <style>
              .logo {
                  display: inline-block;
                  margin-top: 108px;
                  vertical-align: top;
                  background-position: 0 -51px;
                  background-repeat: no-repeat;
                  width: 155px;
                  height: 30px;
                  background-image: url(https://ssl.pstatic.net/static/nid/login/m_sp_00_common_978240a6.png);
                  background-size: 244px 107px;
              }
          </style>
      </head>
      <body>
      	<div class="container-fluid mt-5 ml-5">
              <div class="row">
                  <div class="col-md-3">
                      <form>
                          <div class="form-group text-center">
                              <a href="#" class="logo"></a>
                          </div>
                          <div class="form-group mt-5 border border-1">
                              <ul class="nav nav-tabs nav-justified">
                                  <li class="nav-item">
                                      <a class="nav-link active" href="#">ID 로그인</a>
                                  </li>
                                  <li class="nav-item">
                                      <a class="nav-link" href="#">일회용 번호</a>
                                  </li>
                                  <li class="nav-item">
                                      <a class="nav-link" href="#">QR코드</a>
                                  </li>
                              </ul>
                              <div class="tab-pane fade show active mt-4 mb-4">
                                  <div class="form-group">
                                      <label class="ml-3" for="memberId">회원 아이디</label>
                                      <input type="text" class="form-control ml-3" style="width: 90%;" id="memberId">
                                  </div>
                                  <div class="form-group">
                                      <label class="ml-3" for="memberPw">회원 비밀번호</label>
                                      <input type="text" class="form-control ml-3" style="width: 90%;" id="memberPw">
                                  </div>
                              </div>
                          </div>
                          <div class="form-group mt-3">
                              <button type="button" id="exAxios" class="btn btn-success btn-lg btn-block">로그인</button>
                          </div>
                      </form>
                  </div>
              </div>   
          </div>
          
      	<script type="text/javascript">
              const $exAxios = document.querySelector('#exAxios');
              $exAxios.addEventListener('click', function(){
                  // 로그인폼의 유효성검사(빈값여부)
                  const $inputEles = document.querySelectorAll('form input');
                  const inputArr = Array.from($inputEles);
                  let isBrake = false;
                  const loginInfo = {};
                  inputArr.some(item => {
                      const inputData = item.value;
                      if(     typeof inputData == 'undefined'
                          ||  inputData == null
                          ||  inputData == ''                 ){
                          alert('필수 입력항목입니다.');
                          item.focus();
                          isBrake = true;
                          return true;
                      }
                      loginInfo[item.id] = item.value;
                  });
                  if(isBrake) return ;
                  console.log(loginInfo);
      
                  // 로그인처리
                  axios.get('./ex.json')
                       .then(response => {
                          const checkObj = response.data;
                          if(     loginInfo.memberId != checkObj.memberId
                              ||  loginInfo.memberPw != checkObj.memberPw ){
                              alert('입력하신 회원의 정보가 없습니다.');    
                          }else{
                              alert('로그인 성공');
                          }
                       })
              });
      	</script>
          <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      </body>
      </html>
      • ex.json
        {
             "memberId" : "id001"
            ,"memberPw" : "pw001"
            ,"memberName" : "홍01"
            ,"memberEmail" : "홍01@123.123"
            ,"memberAddr" : "123"
        }

04. ajax

  • ajax(Asynchronous JavaScript and XML)
    💡
    비동기적인 웹 애플리케이션의 제작을 위해 표현 정보를 HTML과 CSS, 동적인 화면 출력 및 표시 정보와의 상호작용을 위한 DOM JavaScript, 웹 서버와 비동기적으로 데이터를 교환하고 조작하기 위한 XML, Json, HTML, text 등을 이용하는 웹 개발 방법이다.

    ➡️ 서버 측에 데이터를 요청하고, 데이터의 수신이 완료될 때까지 기다리는 방법과 다르게 Ajax를 이용하여 데이터의 수신을 기다리지 않고 바로 다른 작업을 실행함에 따라 불필요한 페이지의 로딩을 기다리지 않으므로 웹의 속도가 빠르게 반응할 수 있다.

    ✅ 사용하는 이유 : JSON이나 XML형태로 필요한 데이터만 받아 갱신하기 때문에 그만큰의 자원과 시간을 아낄 수 있다.

    👉🏻
    동작원리

    1) 클라이언트에서 자바스크립트 함수를 통해 AJAX요청을 한다.

    2) XMLHttpRequest 객체의 인스턴스가 생성된다.

    3) XMLHttpRequest를 통해 현재 HTML의 상태를 가진 XML 메시지를 구성하여 웹서버로 요청한다.

    4) 웹서버에서 처리 후 응답값을 XML 메시지를 보내 XMLHttpRequest 객체가 수신한다.

    5) 수신된 XML 메시지를 파싱하여 데이터를 업데이트한다.

    👉🏻
    구문

    $.ajax({

    data : 요청시 쿼리파라미터. ex) data : {’키’ : 값, ‘키’ : 값 …. }

    url : 요청할 url(서버 주소)

    Type(method) : 통신방식(POST/GET(기본값))

    dataType : 응답 받을 데이터의 타입을 선택 (json(기본값), xml, html, text, document, arraybuffer, stream 등)

    contentType : 서버에 데이터를 보낼 때 형식을 지정 (application/json)

    async : true(기본값) / false(동기로 변환)

    beforeSend : HTTP 요청 전 발생하는 이벤트 핸들러

    success : HTTP 요청 성공시 이벤트 핸들러

    error : HTTP 요청 실패시 이벤트 핸들러

    complete : HTTP 요청 완료시 이벤트 핸들러

    })

    ➡️ 관련 메소드 체이닝

    done : http 요청이 성공하면 done() 메소드에 data를 전달

    fail : http 요청이 실패하면 오류와 상태에 관한 정보가 fail() 메소드에 전달

    always : http 요청이 성공하거나 실패하는 것에 상관없이 무조건 always() 메소드 항상실행

    • Ajax 코드 예제
      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title>비동기통신</title>
          <link rel="icon" href="data:,">
          <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
                integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
          <script src="http://code.jquery.com/jquery-latest.min.js"></script>
          <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
                  integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct"
                  crossorigin="anonymous"></script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
      
      </head>
      <body>
      <h1>비동기통신</h1>
      
      <h2>jQuery - Ajax</h2>
      - jQuery에서도 비동기 통신을 위한 메소드가 존재<br>
      - 별도의 라이브러리가 필요<br>
      - 요청 후 성공 및 실패에 관하여 메소드 체이닝 제공<br>
      - 문법: $.ajax({ 옵션 }) or $.ajax({ 옵션 }).done().fail().always()<br>
      - 대표적인 속성 <br>
      - method : 요청방식(기본값:get)<br>
      - url: 서버주소<br>
      - data: 요청시 쿼리파라미터 ex: data: { '키' : 값 , '키' : 값 ...}<br>
      - dataType : 서버가 응답해주는 데이터의 타입 지정 (arraybuffer, document, json(기본값), text, stream, blob)<br>
      - success : function(data){} , 요청 성공시 이벤트 핸들러<br>
      - error : function(jqXHR, textStatus){}, 요청 실패시 이벤트 핸들러<br><br><br>
      
      - 관련 메소드 체이닝 <br>
      - done : http 요청 성공하면 요청한 데이터 done(data)메소드에 전달<br>
      - fail : http 요청 실패하면 오류와 상태에 관한 정보가 fail(jqXHR, textStatus)메소드에 전달<br>
      - always : http 요청 성공하거나 실패하는 것에 상관없이 always()메소드 항상실행<br><br><br>
      
      - 공공 API <br>
      - 사이트 : https://www.data.go.kr<br>
      - data: 기상청_단기예보 ((구)_동네예보) 조회서비스<br>
      
      <div class="container-fluid mt-5 ml-5">
          <div class="row">
              <div class="col-md-3">
                  <div class="card">
                      <h5 class="card-header">
                          <button type="button" id="exAjax" class="btn btn-success btn-lg btn-block">예보 날씨 확인</button>
                      </h5>
                      <div class="card-body text-center">
                          <h3 class="card-title">날씨정보</h3>
                          <div class="card-text">
                              <form>
                                  <div class="form-group row justify-content-center">
                                      <div class="col-sm-12">
                                          <input type="text" readonly class="form-control-plaintext text-center text-primary"
                                                 id="curDate" value="">
                                      </div>
                                  </div>
                                  <div class="form-group row justify-content-center">
                                      <label for="curTemp" class="col-sm-4 col-form-label">현재기온</label>
                                      <div class="col-sm-4">
                                          <input type="text" readonly
                                                 class="form-control-plaintext text-center text-info font-weight-bolder"
                                                 id="curTemp" value="">
                                      </div>
                                  </div>
                                  <div class="form-group row justify-content-center">
                                      <label for="curSky" class="col-sm-4 col-form-label">하늘상태</label>
                                      <div class="col-sm-4">
                                          <input type="text" readonly
                                                 class="form-control-plaintext text-center text-info font-weight-bolder"
                                                 id="curSky" value="">
                                      </div>
                                  </div>
                                  <div class="form-group row justify-content-center">
                                      <label for="proRain" class="col-sm-4 col-form-label">강수확률</label>
                                      <div class="col-sm-4">
                                          <input type="text" readonly
                                                 class="form-control-plaintext text-center text-info font-weight-bolder"
                                                 id="proRain" value="">
                                      </div>
                                  </div>
                                  <div class="form-group row justify-content-center">
                                      <label for="humidity" class="col-sm-4 col-form-label">습도</label>
                                      <div class="col-sm-4">
                                          <input type="text" readonly
                                                 class="form-control-plaintext text-center text-info font-weight-bolder"
                                                 id="humidity" value="">
                                      </div>
                                  </div>
                              </form>
                          </div>
                      </div>
                  </div>
              </div>
          </div>
      </div>
      <script type="text/javascript">
          /*
              POP	강수확률	%	8
              PTY	강수형태	코드값	4
              PCP	1시간 강수량	범주 (1 mm)	8
              REH	습도	%	8
              SNO	1시간 신적설	범주(1 cm)	8
              SKY	하늘상태	코드값	4
              TMP	1시간 기온	℃	10
              TMN	일 최저기온	℃	10
              TMX	일 최고기온	℃	10
              UUU	풍속(동서성분)	m/s	12
              VVV	풍속(남북성분)	m/s	12
              WAV	파고	M	8
              VEC	풍향	deg	10
              WSD	풍속	m/s	10
      
              하늘상태	전운량
              맑음	0 ~ 5
              구름많음	6 ~ 8
              흐림	9 ~ 10
              ['POP','REH','SKY','TMP','TMN','TMX']
              - Base_time : 0200, 0500, 0800, 1100, 1400, 1700, 2000, 2300 (1일 8회)
              - API 제공 시간(~이후) : 02:10, 05:10, 08:10,
                                  11:10, 14:10, 17:10, 20:10, 23:10
          */
      
          // 
          // ajax 요청시 요청 데이터를 반환하는 함수
          function paramFn(now) {
              let baseDate = now.format('YYYYMMDD');
              let baseTime = Number(now.format('HHmm'));
              console.log(baseDate, '||', baseTime);
      
              // api 요청 시간 조정
              if (baseTime > 2310) {
                  baseTime = '2300';
              } else if (baseTime > 2010) {
                  baseTime = '2000';
              } else if (baseTime > 1710) {
                  baseTime = '1700';
              } else if (baseTime > 1410) {
                  baseTime = '1400';
              } else if (baseTime > 1110) {
                  baseTime = '1100';
              } else if (baseTime > 810) {
                  baseTime = '0800';
              } else if (baseTime > 510) {
                  baseTime = '0500';
              } else if (baseTime > 210) {
                  baseTime = '0200';
              } else {
                  baseDate = now.subtract(1, 'd').format('YYYYMMDD');
                  baseTime = '2300';
              }
      
              // 필요한 데이터를 더 가공해서 만들기
              let curDate = now.format('YYYYMMDD');
              let curTime = (baseTime == now.format('HH00')) ? now.add(1, 'h').format('HH00') : now.format('HH00');
      
              const paramObj = {
                  'curDate': curDate,
                  'curTime': curTime,
                  'param': {
                      'serviceKey': 'fbVE/K2iXGg+ZUnwxHuXLvK8nhPdz2YumV6zzW53wu4rn6KOG19ex5xs4uderScb5Qw8vGqxtbDKV5FUA0ymDg==',
                      'pageNo': '1',
                      'numOfRows': '60',
                      'dataType': 'JSON',
                      'base_date': baseDate,
                      'base_time': baseTime,
                      'nx': 63,
                      'ny': 89
                  }
              }
              return paramObj;
          }
      
      
          $('#exAjax').click(function () {
              console.log(moment());
              const paramObj = paramFn(moment());
              console.log(paramObj);
      
              const request = $.ajax({
                  url: "https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst",
                  method: "GET",
                  data: paramObj.param,
                  dataType: "JSON"
              });
      
              request.done(function (response) {
                  console.log(response);
                  const dataArr = response.response.body.items.item;
                  console.log(dataArr);
      
                  // 화면에 출력
                  let castTime = `${moment(paramObj.curDate + " " + paramObj.curTime).format('YYYY년 MM월 DD일 HH시 mm분 기준')}`
                  console.log(castTime);
                  const castObj = {'예보기준': castTime};
                  // reduce(callback(), 초깃값) 누적하는 함수
                  // function(result, curItem)
                  // 1. 초깃값(객체)이 result 인수에 맨처음 쌓인다.
                  // 2. curItem 인수는 each 문처럼 배열 안의 수만큼 계속 순회.
                  dataArr.reduce(function (result, curItem) {
                      if (curItem.fcstDate == paramObj.curDate && curItem.fcstTime == paramObj.curTime) {
                          switch (curItem.category) {
                              case 'POP':
                                  result['강수확률'] = curItem.fcstValue + '%';
                                  break;
                              case 'REH':
                                  result['습도'] = curItem.fcstValue + '%';
                                  break;
                              case 'SKY':
                                  // curItem.fcstValue 의 숫자만 보고는 하늘 상태를 모른다.
                                  let skyValue = Number(curItem.fcstValue);
                                  let status = '';
                                  if (skyValue >= 9) {
                                      status = '흐림';
                                  } else if (skyValue >= 6) {
                                      status = '구름많음';
                                  } else {
                                      status = '맑음';
                                  }
      
                                  result['하늘상태'] = status;
                                  break;
                              case 'TMP':
                                  result['현재기온'] = curItem.fcstValue + '℃';
                                  break;
                          }
                      }
                      // result[curItem.category] = curItem.fcstValue;
                      return result;
                  }, castObj) // 초기값
                  console.log(castObj);
      
                  $('#curDate').val(castObj['예보기준']);
                  $('#curTemp').val(castObj['현재기온']);
                  $('#curSky').val(castObj['하늘상태']);
                  $('#proRain').val(castObj['강수확률']);
                  $('#humidity').val(castObj['습도']);
              });
      
              request.fail(function (jqXHR, textStatus) {
                  alert("Request failed: " + textStatus);
              });
      
          });
      
      </script>
      <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
      </body>
      </html>

    🗣
    moment 라이브러리
    • 설치 : <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
    • moment 라이브러리는 날짜 형식을 간편하게 조작할 수 있는 자바스크립트 라이브러리입니다
    • add : 현재 날짜에서 지정된 정수값만 큼 연, 월, 일 더하기를 수행합니다. ex) add(5, ‘m’) → 5 month 더하기
    • subtract : 현재 날짜에서 지정된 정수값만 큼 연, 월, 일 빼기를 수행합니다. ex) subtract(1, ‘d’) → 1 day 빼기

    reduce 함수

    • 배열의 각 요소를 순회하며 callback함수의 실행 값을 누적하여 하나의 결과값을 반환한다.
    • arr.reduce(callback(accumulator, currentValue), 초깃값))
    • accumulator : callback함수의 반환값을 누적한다.
    • currentValue : 배열의 현재 요소
    • 초깃값이 맨처음 쌓이고, 그 뒤로 반환값이 쌓인다.


tag : #node.js #javascript #비동기통신 #fetch #axios #ajax #promise #async #await #moment #reduce


Uploaded by N2T

728x90
320x100

'0년차 > Javascript' 카테고리의 다른 글

[Javascript] jQuery  (0) 2023.08.19
[Javascript] DOM객체 이벤트  (0) 2023.05.20
[Javascript] DOM(Document Object Model)  (0) 2023.05.14
[Javascript] 브라우저렌더링, 브라우저 객체(BOM)  (1) 2023.05.14
[Javascript] 예외처리  (0) 2023.04.29
Comments