티스토리 뷰

#Promise #.then #.catch

  • Promise 객체를 생성할 때 인자로 받는 callback 함수인 resolve와 reject는 비동기 처리가 성공/실패했을 경우 전달할 인자와 함께 호출된다. => T
  • Promise 객체의 .then 메서드는 오류 없이 resolve 되었을 때 실행되는 함수이며 .catch 메서드는 도중에 오류가 발생하여 reject 되었을 때 실행되는 함수이다 => T

 

Asynchronous Javascript 비동기 자바스크립트 1 #single -threaded # non-blocking #setTimeout #WebAPI #CallStack #TaskQu

#single -threaded #setTimeout #WebAPI #CallStack #TaskQueue #CouncurrenyModel JavaScript는 single threaded 언어로 한 번에 한 가지 일 밖에 처리하지 못한다. => T Event Loop는 Call Stack이 비워지면 Tas..

ninefloor-design.tistory.com

앞서 게시물에서 동시성 모델을 살펴보았다.

여기서는 Web API로 들어오는 순서는 중요하지 않고, 어떤 이벤트가 먼저 처리되느냐가 중요해진다.

즉, 실행 순서가 불명확하다. (제로 딜레이도 있기 때문)

이러한 문제를 해결하기 위해 비동기 처리를 할 때 작성 방식을 따로 구현한다.

 

순차적 비동기 처리를 위한 방법

첫 번째가 Async callback 이다. 

두 번째는 promise-style 이다.

 

Async callbacks 비동기 콜백

비동기 콜백 함수란?

" 비동기 작업이 완료된 후 코드를 계속 실행하기 위해 사용하는 함수"

(일급 객체 - 인자로 넘길 수 있고, 리턴값으로 사용할 수 있고, 변수에 할당할 수 있다. )

  • 백그라운드 코드 실행이 끝나면 callback 함수를 호출하여 다음 작업을 실행하거나 작업 완료를 알린다.
  • callback 함수를 다른 함수의 인수로 전달할 때, 함수의 참조로 인수를 전달하는 것이지 즉시 실행되는 것이 아니다.
  • 즉, 비동기 로직을 수행할 때 다른 함수의 '매개변수'로 전달되어 특정 시점(명시적 호출이 아닌 특정 조건)에서 호출할 수 있는 callback 함수를 사용하는 것이다.
<script>
    // 1. My Custom Callback Function
    const myFunc = function (func) {
      return func
    }

    const myArgumentFunc = function () {
      return 'Hello'
    }

    const result = myFunc(myArgumentFunc)
    console.log(result())

    // 2. map
    const nums = [1, 2, 3]
    const doubleNums = nums.map(num => {
      return num * 2
    })
    // or
    const doubleNums = nums.map(function (num) {
      return num * 2
    })

    console.log(doubleNums)


    // 3. Array Helper Method 
    const numbers = [1, 2, 3]
    const newNumbers = []

    numbers.forEach(num => {
      newNumbers.push(num + 1)
    })

    console.log(newNumbers)


    // 4. setTimeout
    // unhappy coding 출력, 3초 있다가 happy coding 출력
    const helloWorld = function () {
      console.log('happy coding')
    }
    setTimeout(helloWorld, 3000)
    console.log('unhappy coding')


    // 5. addEventListener
    const myButton = document.querySelector('button')
    
    myButton.addEventListener('click', function () {
      console.log('button clicked!'
      )
    })

  </script>
</body>

 

wow..! but.. there could be a Callback hell

순차적으로 비동기 작업을 처리하기 위해 호출을 반복하다보면 콜백 지옥을 마주하게 된다.

이렇게 되면 디버깅이 어려워지고 코드 가독성이 떨어지므로 해결해야한다.

 

---> 해결?


Promise callbacks

Promise callback 방식을 사용하여 callback hell 를 해결할 수 있다.

 

Promise object란?

비동기 작업의 최종 완료 또는 실패를 나타내는 객체.

미래의 어떤 상황에 대한 약속. 순서 보장. 가독성 보장.

.then() 과 .catch() 메서드는 모두 promise를 반환하기 때문에 chaining이 가능하다.

단, .then() 메서드의 경우 반환 값이 반드시 있어야 한다!

 

.then(함수) : 성공에 대한 약속 (이전 작업이 성공하면 ~한다.)

이전 작업(promise)이 성공했을 때 수행할 작업을 나타내는 callback 함수이다.

각 callback 함수는 이전 작업의 성공 결과를 인자로 전달받는다.

성공했을 때의 코드를 callback 함수 안에 작성한다.

 

.catch(함수) : 실패에 대한 약속 (이전 작업이 실패하면 ~한다.)

.then이 하나라도 실패하면 동작한다.

이전 작업의 실패로 생성된 error 객체를 사용한다.

 

.finally(함수)

결과와 상관없이 무조건 지정된 callback 함수가 실행된다.

어떠한 인자도 전달받지 않으며 무조건 실행되어야 하는 절에서 활용한다.

 

 

response.data.title

<body>
  <!-- axios CDN -->
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    const URL = 'https://jsonplaceholder.typicode.com/todos/1/'
    const myPromise = axios.get(URL)

    axios.get(URL)
      // console.log(response.data.title)을 3단계로 풀기 for 콜백지옥 해결
      .then(response => {
        console.log(response)
        return response.data
      })
      .then(response => {
        return response.title
      })
      .then(response => {
        console.log(response)
      })
      // error 객체 
      .catch(error => {
        console.log(error)
      })
      // 인자 전달 없이 무조건 실행
      .finally(function () {
        console.log('나는 에러가 나도 실행')
      })
 
  </script>
</body>

 


Axios

"Promise based HTTP client for the browser and Node.js"

"브라우저를 위한 Promise 기반의 클라이언트"

  • 응답을 Promise 객체(response)로 준다. (axios.get()) 의 리턴 값이 promise 객체임.
  • XHR이라는 내장 객체 대신, AJAX 요청을 처리한다! XMLHttpRequest를 대체한다.
  • Vue.js 에서 요청을 보내는 라이브러리.

axios.get(URL)  => 해당 URL로 요청을 보낸다. 성공 객체를 받으면 .then의 인자로 넣어 넘긴다.

 

Axios를 활용하여 버튼 누르면 이미지 출력되게 만들기

 

<!-- axios CDN을 삽입한다. -->

// axios를 사용하여 URL로 GET 요청을 보내고 Promise 객체를 받는다.

// .then 메서드를 통해 요청이 성공적인 경우의 콜백함수를 정의한다.

// 응답객체의 데이터에서 이미지에 대한 리소스를 img 요소의 src 속성으로 할당한다.

<body>
  <button>댕댕이</button>
  <div class="dog-box">

  </div>
  <!-- axios CDN -->
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    const URL = 'https://dog.ceo/api/breeds/image/random'
    const myButton = document.querySelector('button')
    const box = document.querySelector('.dog-box')

    // 순서주의 ! 버튼을 클릭할 때마다 axios가 실행, dog api로 요청을 보낸다.
    myButton.addEventListener('click', function() {
      axios.get(URL)
      .then(res => {
        const dogUrl = res.data.message

        const imgTag = document.createElement('img')
        imgTag.setAttribute('src', dogUrl)
        box.appendChild(imgTag)
        })
        
      .catch(res => {
        console.log(error)
      })
    })

    </script>
</body>

 

 


async & await

  • 비동기 코드를 작성하는 새로운 방법
  • 기존 Promise 시스템 위에 구축된 syntactic suger로 보다 직관적으로 코드를 읽을 수 있다.
  • Promise 구조의 .then chaining 을 없앤다.
댓글