jquery를 js로 삽질

김금동·2021년 10월 14일
0

javascript

목록 보기
1/2
post-thumbnail

바꿀 코드

$(document).ready(function(){
    exchangeRate()
    showList()
});
function exchangeRate(){

    $.ajax({
      type: "GET",
      url: "http://spartacodingclub.shop/sparta_api/rate",
      data: {},
      success: function(response){
          let rate = response['rate']
          $('#exchange-rate').text(rate)
      }
    })
}
function completeOrder() {
    const name = $('#user-name').val()
    const number = $('#user-number').val()
    const address = $('#user-address').val()
    const call = $('#user-call').val()
    $.ajax({
        type: "POST",
        url: "/order",
        data: {
            'name':name,
            'number':number,
            'address':address,
            'call':call,
        },
        success: function (response){
            console.log(response['msg'])
        }
    })
}
function showList(){
    $.ajax({
        type: "GET",
        url: "/order",
        data: {},
        success: function (response){
            let userInfo = response['all_userInfo']
            for (let i = 0; i < userInfo.length; i++){
                let name = userInfo[i]['name']
                let number = userInfo[i]['number']
                let address = userInfo[i]['address']
                let call = userInfo[i]['call']

                let temp_html = `<tr>
                                    <th scope="row">${name}</th>
                                    <td>${number}</td>
                                    <td>${address}</td>
                                    <td>${call}</td>
                                </tr>
                `
                $('#info-list').append(temp_html)
            }
        }
    })
}

(Flask 쓰는중)
첫번째로는 ready()를 고치자

$(document).ready(function(){
     exchangeRate()
     showList()
});

비슷한 이벤트가 load와 DOMContentLoaded가 있는데 MDN에선

load는 The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images.

DOMContentLoaded는 The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

저 두 함수는 모든 컨텐츠 로드되는 걸 기다릴 필요가 없으므로 DOMContentLoaded로 하자.

window.addEventListener('DOMContentLoaded', (event) => {
    exchangeRate()
    showList()
})

이번엔 ajax를 고치자

function exchangeRate(){
$.ajax({
       type: "GET",
       url: "http://spartacodingclub.shop/sparta_api/rate",
       data: {},
       success: function(response){
           let rate = response['rate']
          $('#exchange-rate').text(rate)
       }
     })
}

ajax의 js버전인 fetch()로 바꾸자

async function exchangeRate(){
    const RATE_URL = "http://spartacodingclub.shop/sparta_api/rate"
    const rate = await fetch(RATE_URL,{
        method: "GET",
        headers: {
            'Content-Type': 'application/json;charset=utf-8'
        },
    }).then(response => response.json()).then(data => data.rate)
    const $exchangeRate = document.querySelector('#exchange-rate')
    $exchangeRate.innerText = rate

원래는 fetch()로만 만들어서 then지옥으로 만드려고 했는데 친구가 그것 보단 이렇게 쓰는게 좋다고 해서 바꿨다.
fetch앞에 await써서 rate에 값주는 거 기다린후 innerText로 박았다. 함수안에 await쓰면 function앞에 async붙여주란다.

ajax js로

function showList(){
$.ajax({
         type: "GET",
         url: "/order",
         data: {},
         success: function (response){
             let userInfo = response['all_userInfo']
             for (let i = 0; i < userInfo.length; i++){
                 let name = userInfo[i]['name']
                 let number = userInfo[i]['number']
                 let address = userInfo[i]['address']
                 let call = userInfo[i]['call']

                 let temp_html = `<tr>
                                     <th scope="row">${name}</th>
                                     <td>${number}</td>
                                     <td>${address}</td>
                                     <td>${call}</td>
                                 </tr>
                 `
                 $('#info-list').append(temp_html)
             }
         }
     })
}

아까랑 비슷한 유형이다. 밑에 있는 append()부분만 다르다.

async function showList(){
    const userInfo = await fetch('/order',{
        method: "GET",
        headers: {
            'Content-Type': 'application/json;charset=utf-8'
        },
    }).then(response => response.json()).then(data => data['all_userInfo'])
    const $infoList = document.querySelector('#info-list')
    for (let i = 0; i < userInfo.length; i++){
        let name = userInfo[i]['name']
        let number = userInfo[i]['number'] 
        let address = userInfo[i]['address']
        let call = userInfo[i]['call']
        let temp_html = `<tr>
                            <th scope="row">${name}</th>
                            <td>${number}</td>
                            <td>${address}</td>
                            <td>${call}</td>
                        </tr>
                        `
        $infoList.insertAdjacentHTML('beforeend',temp_html)
    }

예전에 친구가 js막 만질 때 insertAdjacentHTML()가 정말 좋다면서 설명해줬는데 갑자기 생각나서 빨리 찾았다. insertAdjacentHTML()로 데이터가져온 후 테이블에 넣어줬다.

사실 이 부분때문에 이 게시물을 썼다.
방금 전까지는 ajax get형식이였는데 이번엔 ajax post형식이다.

function completeOrder() {
    let name = $('#user-name').val()
    let number = $('#user-number').val()
    let address = $('#user-address').val()
    let call = $('#user-call').val()
    $.ajax({
        type: "POST",
        url: "/order",
        data: {
            'name':name,
            'number':number,
            'address':address,
            'call':call,
        },
        success: function (response){
            console.log(response['msg'])
        }
    })
}

post 형식으로 보낼때 처음엔 걍 생각없이
headers부분에
'Content-Type': 'application/json'박고
body도 JSON.stringify({})형태로 보냈는데

400bad request unexpected token < in json at position 0

이 에러가 떠서 계속 내 노트북과 눈싸움을 한 후, 처음에 생각없이 너무 당연하게 넣은 content-type을 의심하여
ajax가 서버로 보낸 data타입을 보니까 json이 아니였다.
application/x-www-form-urlencoded 이런 타입으로 보냈다.

(ajax가 보낸 데이터 타입 확인은 flask의 request객체를 이용해서 request.content_type으로 확인했다.)

body부분은 위 타입을 google에 치니까 mdn에서

application/x-www-form-urlencoded: the keys and values are encoded in key-value tuples separated by '&', with a '=' between the key and the value. Non-alphanumeric characters in both keys and values are percent encoded: this is the reason why this type is not suitable to use with binary data (use multipart/form-data instead)

라고 하길래 이렇게 넣었다.

async function completeOrder() {
    const name = document.querySelector('#user-name').value
    const number = document.querySelector('#user-number').value
    const address = document.querySelector('#user-address').value
    const call = document.querySelector('#user-call').value
    const msg = await fetch('/order',{
        method: "POST",
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        },
        body: `name=${name}&number=${number}&address=${address}&call=${call}`
    })
    .then(response => response.json()).then(data => data['msg'])
    .catch(error => console.log(error))
    console.log(msg)
}

추가
content-type부분이 찜찜해서 더 찾아본 결과
flask documentation에서

property form: ImmutableMultiDict[str, str]
The form parameters. By default an ImmutableMultiDict is returned from this function. This can be changed by setting parameter_storage_class to a different type. This might be necessary if the order of the form data is important.

즉,데이터를 parmeter형식으로 받은걸 immutableMultiDict로 리턴해준단다.
그러니까 데이터를 보낼 땐 name='엄준식'&age='13' 이런식으로 보내야지 request.form을 해주면
데이터가 MultiDict([(name, 엄준식),(age,13)]) 이렇게 된다.
그래서 엄준식이란 데이터를 얻고싶으면 request.form['name']을 쓰면 되는 것 이었다.('name'이 key이고 '엄준식'이 value)

A MultiDict can be constructed from an iterable of (key, value) tuples, a dict, a MultiDict or from Werkzeug 0.2 onwards some keyword parameters.
https://werkzeug.palletsprojects.com/en/2.0.x/datastructures/#werkzeug.datastructures.MultiDict

참고로 request.form은 post나 put요청에만 쓸 수 있다고 한다.

Changed in version 0.9: Previous to Werkzeug 0.9 this would only contain form data for POST and PUT requests.

그리고 fetch에서 headers의 content-type부분을 지우고 전송해봤는데 안보내진다. 즉, content-type명시도 까먹으면 안된다.

다시 생각해보니 jquery로 쓴 ajax는 자동으로 content-type도 명시해준거고 data 형식도 자동으로 바꿔서 보내준거였다.

관련 깃헙:https://github.com/golddong98/prac

바꾼코드

window.addEventListener('DOMContentLoaded', (event) => {
    exchangeRate()
    showList()
})

async function exchangeRate(){
    const RATE_URL = "http://spartacodingclub.shop/sparta_api/rate"
    const rate = await fetch(RATE_URL,{
        method: "GET",
        headers: {
            'Content-Type': 'application/json;charset=utf-8'
        },
    }).then(response => response.json()).then(data => data.rate)
    const $exchangeRate = document.querySelector('#exchange-rate')
    $exchangeRate.innerText = rate

}
async function completeOrder() {
    let name = document.querySelector('#user-name').value
    let number = document.querySelector('#user-number').value
    let address = document.querySelector('#user-address').value
    let call = document.querySelector('#user-call').value
    const msg = await fetch('/order',{
        method: "POST",
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        },
        body: `name=${name}&number=${number}&address=${address}&call=${call}`
    })
    .then(response => response.json()).then(data => data['msg'])
    .catch(error => console.log(error))
    console.log(msg)

}
async function showList(){
    const userInfo = await fetch('/order',{
        method: "GET",
        headers: {
            'Content-Type': 'application/json;charset=utf-8'
        },
    }).then(response => response.json()).then(data => data['all_userInfo'])
    const $infoList = document.querySelector('#info-list')
    for (let i = 0; i < userInfo.length; i++){
        let name = userInfo[i]['name']
        let number = userInfo[i]['number'] 
        let address = userInfo[i]['address']
        let call = userInfo[i]['call']
        let temp_html = `<tr>
                            <th scope="row">${name}</th>
                            <td>${number}</td>
                            <td>${address}</td>
                            <td>${call}</td>
                        </tr>
                        `
        $infoList.insertAdjacentHTML('beforeend',temp_html)
    }

}

결론:무지성 json거인이 되지말자하

profile
나원래chu해

0개의 댓글