[JS] async-await

Jang·2022년 9월 30일
0

학원

목록 보기
17/26

비동기처리에 대한 이해가 부족해서 조금이나마 이해한 내용을 정리해보려고 한다.

수업시간에 실습한 페이지

  • 처음에 열리는 페이지
  • 이름을 클릭하면 새로운 html창이 열리고 그 이름의 id를 주소창에 저장하여 (~~/?id=10103) 해당 id에 대한 정보를 백엔드에서 가져와 JS를 이용해 html태그를 삽입하여 화면에 출력함


추가할 내용

여기에서 정보 페이지 밑에 학생들의 이름이 전부 적혀있는 버튼을 만들어보려고 했다.
(현재 표시되는 학생은 강조)

step1

<script type="module">
      import ajaxHelper from "../../../helper/AjaxHelper.js";

      let json2 = null;
      (async () => {
        try {
          json2 = ajaxHelper.requestAsync("http://localhost:3001/student");
        } catch (e) {
          console.error(e);
          alert(`[${e.status}] ${e.text}\n${e.msg}`);
          return;
        }

        const getData = () => {
          json2.then((appData) => {
            for (let key2 in appData) {
              console.log(appData[key2].name);
              const li2 = document.createElement("li");
              li2.innerHTML = appData[key2].name;
              li2.classList.add(appData[key2].id);
              li2.classList.add("name");
              document.querySelector("#list2").appendChild(li2);
              li2.addEventListener("click", (e) => {
                location.search = "id=" + appData[key2].id;
              });
            }
          });
        };

        getData();
      })();
    </script>

html에는 ul#list2를, Js에는 <script type="module">을 하나더 추가함.
원래 json2를 바로 쓰려고 했으나 console.log(json2)을 바로 찍어보니

Promise 타입이 나와 사용할 수가 없었다.
검색해보니 Promise타입에서 그 안의 값인 PromiseResult를 사용하려면

function getPromise() {
  return fetch(endpoint)
    .then(res => res.json())
    .then(funcData => console.log(`이것이 바로 우리가 추출하고 싶어하는 value : ${funcData}`)
}

const promise = getPromise();
const getData = () => {
  promise.then((appData) => {
    console.log(appData);
  });
};

getData()  
// 출처:https://velog.io/@zzero9158/javascript-promise%EC%9D%98-%EA%B0%92-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0

이런 함수를 거쳐야 하고 .then => {} 안에 코드를 작성해야 한다.
내 생각엔 비동기처리를 순차적으로 진행하려면 연결을 확실히 해야 하는 것 같다.


step2

    <script type="module">
      import ajaxHelper from "../../../helper/AjaxHelper.js";
      import utilHelper from "../../../helper/UtilHelper.js";

      const URL = "http://localhost:3001/student";

      // 생성된 객체를 JSON으로 변환
      // const query = new URLSearchParams(location.search);
      // const params = Object.fromEntries(query);
      // console.log(params.id);

      const params = utilHelper.getUrlParams();

      (async () => {
        let json = null;
        try {
          json = await ajaxHelper.requestAsync(`${URL}/${params.id}`);
        } catch (e) {
          alert(`[${e.status}] ${e.text}\n${e.msg}`);
          return;
        }

        const list = document.querySelector("#list");
        for (const key in json) {
          const li = document.createElement("li");
          li.innerHTML = `<strong>${key}</strong>: ${json[key]}`;
          list.appendChild(li);
        }

      // ----------------------------- 추가한 내용 ------------------------
      
        let add = null;
        add = await document.querySelectorAll(".name").forEach((v, i) => {
          if (v.classList.contains(params.id)) {
            v.classList.add("active");
      // -----------------------------------------------------------------
          }
        });
      })();
    </script>

이런식으로 기존 코드 밑에 추가했는데 새로고침을 누르면 어쩔땐 제대로 색상이 강조가 되고 어쩔땐 제대로 적용되지 않았다.



예상 원인

  • 추측하기로는 비동기 처리를 두개의 트랙?으로 따로 진행했는데 로딩속도의 차이로 어쩔땐 코드가 다 처리되지 않은 상태에서 내가 추가한 코드를 실행해서 없는 list를 가지고 forEach를 돌리는 꼴이 되는 것 같다.
    2개의 트랙을 하나로 합치고 가장 마지막에 코드를 추가하면 해결될것이라 생각된다.

  • 그런데 그 전에 비동기처리에 대해 이해가 많이 부족하다고 느껴서
    비동기처리 특히 async await와 promise에 대해서 더 공부한 후에 코드를 깔끔하게 정리해보려고 한다.





해결

2022-10-03

    <script type="module">
      import ajaxHelper from "../../../helper/AjaxHelper.js";
      import utilHelper from "../../../helper/UtilHelper.js";

      const URL = "http://localhost:3001/student";

      const params = utilHelper.getUrlParams();

      (async () => {
        let json = null;
        let json2 = null;

        try {
          json = await ajaxHelper.requestAsync(`${URL}/${params.id}`);
          json2 = await ajaxHelper.requestAsync(URL);
        } catch (e) {
          alert(`[${e.status}] ${e.text}\n${e.msg}`);
          return;
        }

        console.log(json);
        const list = document.querySelector("#list");
        for (const key in json) {
          const li = document.createElement("li");
          li.innerHTML = `<strong>${key}</strong>: ${json[key]}`;
          list.appendChild(li);
        }

        console.log(json2);
        const list2 = document.querySelector("#list2");
        for (const key2 in json2) {
          console.log(json2[key2]);
          const li2 = document.createElement("li");
          const a = document.createElement("a");
          a.innerHTML = json2[key2].name;
          a.setAttribute("href", `student_info.html?id=${json2[key2].id}`);
          li2.appendChild(a);
          if (json2[key2].id == json.id) {
            li2.classList.add("active");
          }
          list2.appendChild(li2);
        }

        document.createElement();
      })();
    </script>

예상대로 두개의 <script type="module">에서 하나로 합치니 원하는대로 동작하였다.
(비동기처리가 순서대로 진행되었고 원하는 코드를 계산할 때 필요한 다른 코드들이 다 처리된 이후여서 처리결과가 로딩속도와 상관없이 동일해졌다.)
3일 전에는 async await와 try catch를 보고 괜시리 겁을 먹고 사이사이에 코드를 추가하기보다 새로 추가한 코드뭉치들을 여기넣었다가 저기 넣었다가 하면서 실행이 되나 안되나 무식하게 했었는데 (아니면 try catch를 2번 써야하나 하고 추가로 쓴적도 있었다)
동작원리를 다시 복습하고 나니 그냥 try안에서 원하는 비동기 처리마다 await를 추가하면 되는걸 알게되었다. (나머지 코드는 try catch 이후에)

0개의 댓글