Skip to content

Latest commit

 

History

History
180 lines (134 loc) · 5.59 KB

File metadata and controls

180 lines (134 loc) · 5.59 KB

Asynchronous

Asynchronous Request

  • 기본적으로 사용자가 요청을 보낼 때 HTML 페이지를 다시 렌더링 할 수 도있지만, JSON 형태로 response로 보내 줄 수도 있습니다.
  • 이 방법은 기존에 HTML response로 보내주는 방식보다 더 빠른 속도로 통신할 수 있습니다.

프로젝트에 적용하기

product 삭제에 Asynchronous Request 적용하기

  • Client JavaScript를 활용해 DOM 객체를 업데이트 하는 방법을 사용해 봅시다.
  1. views/admin/products.ejs

    • JavaScript 를 적용하기 위해 public/js/admin.js만들고 import하기

      <script src="/js/admin.js"></script>
    • 기존 form 형태로 서버에 request 보내는 대신 Client JavaScript 이용해서 request 데이터 가져오기 기존 코드

      <div class="card__actions">
          <a href="/admin/edit-product/<%= product._id %>?edit=true" class="btn">Edit</a>
          <form action="/admin/delete-product" method="POST">
              <input type="hidden" value="<%= product._id %>" name="productId">
              <input type="hidden" name="_csrf" value="<%= csrfToken %>" />
              <button class="btn" type="submit">Delete</button>
          </form>
      
      </div>

      변경된 코드

      <div class="card__actions">
          <a href="/admin/edit-product/<%= product._id %>?edit=true" class="btn">Edit</a>
          <input type="hidden" value="<%= product._id %>" name="productId">
          <input type="hidden" name="_csrf" value="<%= csrfToken %>" />
          <button class="btn" type="button" onclick="deleteProduct(this)">Delete</button>
      </div>
  2. public/js/admin.js

    • 버튼을 클릭해서 정보 브라우저에서 데이터 가져오기

      const deleteProduct = btn => {
        // <button class="btn" type="button" onclick="deleteProduct(this)">Delete</button>
        console.log(btn);
          
        // productId 가져오는 방법
        // <input type="hidden" value="{productId}" name="productId">
        console.log(btn.parentNode.querySelector('[name=productId]'));
      };
    • vlaue 값 가져오기

      const deleteProduct = btn => {
        const prodId = btn.parentNode.querySelector('[name=productId]').value;
        const csrf = btn.parentNode.querySelector('[name=_csrf]').value;
      };
  3. routes/admin.js

    • 기존 postDeleteProduct 라우터에서 post 요청을 delete 요청으로 바꾸기

      // productId 를 params로 보낸다.
      router.delete('/product/:productId', isAuth, adminController.deleteProduct);
  4. controllers/admin.js

    • postDeleteProduct > deleteProduct 로 수정하기

      exports.deleteProduct = (req, res, next) => {
        // form 요청으로 보내는 것이 아니라 url에서 받음으로
        const prodId = req.params.productId;
        Product.findById(prodId)
          .then(product => {
            if (!product) {
              return next(new Error('Product not Found.'));
            }
            fileHelper.deleteFile(product.imageUrl);
            return Product.deleteOne({ _id: prodId, userId: req.user._id });
          })
          .then(result => {
            console.log(result);
            console.log('DESTROYED PRODUCT');
            // status 코드를 보내주고 json으로 보내줄 데이터를 JavaScript 객체로 보내주면
      	 // 자동으로 json 형식으로 변환해줌
            res.status(200).json({ message: 'Success!' });
          })
          .catch(err => {
            res.status(500).json({ message: 'Error' });
          });
      };
  5. public/js/admin.js

    • fetch() 함수 사용하기

      const deleteProduct = btn => {
        const prodId = btn.parentNode.querySelector('[name=productId]').value;
        const csrf = btn.parentNode.querySelector('[name=_csrf]').value;
      
        // fetch 함수를 통해 서버에 request를 보낸다
        // 이 요청은 admin의 deleteProduct 라우터로 전달된다.
        fetch('/admin/product/' + prodId, {
          method: 'DELETE',
          headers: {
            'csrf-token': csrf
          }
        })
          .then(result => {
            console.log(result);
          })
          .catch(err => {
            console.log(err);
          });
      };

DOM 조작하기

우리가 delete 버튼을 누르면 데이터베이스에서 해당 product가 삭제되는 것을 보았습니다. 이어서 이 요청에 의해 DOM에서도 product가 삭제 되도록 해보겠습니다

  • public/js/admin.js

    const deleteProduct = btn => {
      const prodId = btn.parentNode.querySelector('[name=productId]').value;
      const csrf = btn.parentNode.querySelector('[name=_csrf]').value;
    
        // closet() 가장 가까운 element를 찾아줌
      const productElement = btn.closest('article');
    
      fetch('/admin/product/' + prodId, {
        method: 'DELETE',
        headers: {
          'csrf-token': csrf
        }
      })
        .then(result => {
          return result.json();
        })
        .then(data => {
          console.log(data);
          // 해당 child DOM을 삭제
          productElement.parentNode.removeChild(productElement);
        })
        .catch(err => {
          console.log(err);
        });
    };

이 방법은 페이지가 reload 되는 것이 아니라 Client Side 자바스크립트에 의해서 페이지가 변경되는 것입니다.