자바스크립트 JS/JS 입문 공부일지

자바 스크립트(js) 입문 공부 19. 프로미스promise

Tomitom 2022. 11. 22. 12:57
반응형

프로미스란?

new promise 를 하면 프로미스 객체를 만들 수 있습니다. 

프로미스 객체는 비동기 작업에 대한 약속입니다.  (작업 이후 발생할 완료 또는 실패, 그 결과값) 

비동기 작업이란 언제 끝날지 알 수 없는 독립적인 작업입니다. 

작업의 상태가 시작, 진행중, 완료인 것과 무관하게 프로그램은 계속해서 실행이 됩니다.

 

프로미스 생성 방법

프로미스 객체를 생성하면서 콜백함수처럼 전달합니다. 

 

다음과 같이 비동기 작업을 수행하는 함수가 있을 때,

 

 

이를 promise 객체(약속)를 생성하면서 인자로 전달합니다. 

 

 

Promise 객체에 전달된 함수는 두 가지 콜백 함수를 인자로 받습니다. 
하나는 작업 성공 시 실행되는 함수(resolve), 하나는 실패 시 함수(reject) 입니다. 

어디까지나 매개변수이기 때문에 이름은 통상적으로 쓸 뿐, 반드시 resolve와 reject 를 사용하지 않아도 됩니다. 

 

 

여기에 변수를 선언해서 프로미스를 생성합니다. 

 

 

 

프로미스 생성 과정 

아래 예제를 통해서 과정을 자세하게 살펴볼게요. 

프로미스는 비동기 동작을 따로 지정할 테니, 독립적으로 처리하라는 것으로 

대표적인 것 중 하나가 setTimeout 입니다. 

이 메소드는 타이머 기능으로 기능을 실행하기 전에 이미 비동기 동작이 진행되고 있습니다. 

 

// 프로미스 : 비동기 동작을 따로 지정할 테니, 독립적으로 처리하라 

setTimeout( () => {
    let rn = Math.floor(Math.random() * 10 ) +1 // 1에서 10사이의 랜덤함수를 출력한다. 
    console.log(rn)
} , 3000)   // 3초 정도 후에 동작한다.

 

프로미스의 콜백함수에는 비동기 작업을 포함하는 것이 일반적입니다. 

약속을 만드는 것과 수행하는 것을 다르기 때문에 promise 함수를 우선 만들어보겠습니다. 

 

const rnPromise = new Promise((resolve, reject ) => {          
    setTimeout( () => {
        let rn = Math.floor(Math.random() * 10 ) +1 // 1에서 10사이의 랜덤함수를 출력한다. 
        if (rn % 2 ==1){      //홀수 일 경우 resolve 성공
            resolve(rn)       // 성공 했음에 따른 데이터를 반환할 수 있음
        }else{      // 짝수면 reject 실패 
            reject(rn)        // 실패 했음에 따른 데이터를 반환할 수 있음
        }

    } , 3000)   // 3초 정도 후에 동작한다.     
})

 

약속을 호출할 때에는 간단합니다. 다음과 같이 적어주면 됩니다. 

 

rnPromise

 

성공과 실패, 체이닝 메소드 

 

이렇게 비동기 작업 완료 후 (성공 또는 실패) 이를 처리하기 위해 체이닝 메소드를 이용합니다. 

체이닝 메소드chaning 에는 then 과 catchsms 가 있습니다. 

then 은 성공했을 때, catchsms 는 실패했을 때를 사용합니다. 

그럼 위에 적었던 약속 호출식을 다음과 같이 적을 수 있습니다. 

 

rnPromise.then((resolveData) => {
    console.log("성공한 약속")
    console.log(resolveData)
})

.catch((rejectData) => {
    console.log("실패한 약속")
    console.log(rejectData)
})

 

약속이 성공했을 시에 resolveData를 호출하고 그것을 콘솔에 출력하며 

실패했을 시에는 rejectData를 호출하고 그것을 콘솔에 출력합니다. 

 

 

3초 뒤에 랜덤 숫자를 발췌하겠다는 비동기 동작을 콜백함수가 포함하고 있습니다. 

프로미스는 비동기 동작을 수행하는 함수에다 성공에 대한 데이터와 실패에 대한 데이터에 사용할 함수들을 적용시킵니다. 

즉 프로미스 객체는 성공 시의 콜백 함수와 실패시의 콜백함수를 각각 호출할 수 있습니다. 

 

아래의 예제를 한 번 더 확인해볼게요. 

 

 

2초 후에 무조건 성공하는 약속을 만들었습니다. 상기 코드에서 알 수 있듯  then과 cathsms 는 선택적으로 할 수 있습니다. 

비동기이므로 동기와는 다르게 시간차가 존재하기 때문에 느낌표가 모두 출력된 다음에 성공 값이 실행됩니다.

ES6 이후에는 자바 스크립트 라이브러리에서 비동기 동작 대부분이 프로미스가 반환됩니다. 

리액트를 하면서도 프로미스를 반환받기도 하기 때문에 이에 대한 것을 알아두는 것은 좋습니다.

 

 


 프로미스 활용 예제

프로미스를 활용해서 강아지 사진을 로드하는 것을 해볼게요.

우리가 만들 것은 버튼을 누르면 랜덤으로 강아지 사진을 로드할 수 있는 페이지 입니다. 

 

api 를 이용해서 랜덤 이미지를 가져올 것인데요, 웹 서버에 저장된 이미지 자료를 다운로드 받지 않아도 웹상에서 곧바로 생성할 수가 있습니다.  그 중 강아지 사진을 랜덤으로 출력하는 api 인 dog api 를 소개합니다. 

(이후에 api에 대해서는 자세히 포스팅 할게요!)

 

https://dog.ceo/dog-api/

 

Dog API

Dog CEO's Dog API. Over 20,000 images of dogs programmaticaly accessible by over 120 breeds. Image supplied by the Stanford Dogs Dataset.

dog.ceo

 

강아지에 대한 랜덤 이미지를 받을 수 있는 링크가 있습니다. 

 

 

해당 링크를 복사할 경우 이미지 로드 시에 랜덤 이미지를 생성받을 수 있습니다. 

사이트와 링크가 준비되었다면, 이제 html 과 js 스크립트를 작성해볼게요. 

 

<body>

    <button id = "push"> 사진 요청하기 </button>
    <img src ="" alt = "강아지 사진" id = "dog">
    
    <script src="./script03.js"></script>
</body>

 

버튼을 눌렀을 때 강아지 사진이 로드되어야 하므로, 

누를 수 있는 버튼과 이미지 사진이 로드될 img 블록을 만들어줍니다. 

 

자바스크립트에서 이제 각 세부 항목들을 선택해줍니다. 

const button = document.getElementById("push")
const img = document.getElementById("dog")
const url = "https://dog.ceo/api/breeds/image/random"

 

이제 promise를 생성하겠습니다.

웹상에서 무탈하게 이미지를 로드 받았는지에 대해서 상태 코드에 따른 성공과 실패로 구분하기 위해

HTTP 상태 코드 번호를 기입해주겠습니다. 

 

주요 상태 코드는 요청이 성공적으로 완료되었는지를 보여주는 숫자 코드로 각 숫자마다 의미가 정해져있습니다. 

 

 

상태코드 200이 성공이므로 그것을 resolve 값으로 넣어줄게요. 

const getDog = new Promise((resolve, reject) => {
    
    const request = new XMLHttpRequest()
    request.open("get", url)
    request.addEventListener("load", () => {
        // 상태 코드(status)에 따른 성공 실패 구분
        if( request.status == 200 ){    // 상태코드 200이 되어야 성공
            resolve(JSON.parse(request.response))   // 파싱해서 결과를 resolve.
        }else{  
            reject("요청 실패!")
        }
    } )
    request.send()
})

 

프로미스를 호출하기 전 프로미스의 설정을 마쳤으면, 

버튼을 클릭했을 때 실행되어야 하므로 버튼에 대한 기능 속에 프로미스의 호출 기능을 삽입해줍니다. 

 

// 프로미스 호출을 버튼 클릭시에 한다 
// 성공시에는 img 태그에 이미지를 src 를 지정하게끔 한다 

button.addEventListener("click",function(){

    getDog.then((resolveData)=>{
        img.src = resolveData.message
    })

    .catch((rejectedData)=>{
        console.log(rejectedData)
    })
})

 

실행화면은 다음과 같습니다. 

 

너무 귀여워

 

코드 전문은 더보기에 넣어둘게요. 

 

<html>

더보기
<body>


    <button id = "push"> 사진 요청하기 </button>
    <img src ="" alt = "강아지 사진" id = "dog">
   
    <script src="./script03.js"></script>
</body>

 

<js script>

더보기

 

const button = document.getElementById("push")
const img = document.getElementById("dog")
const url = "https://dog.ceo/api/breeds/image/random"


const getDog = new Promise((resolve, reject) => {
   
    const request = new XMLHttpRequest()
    request.open("get", url)
    request.addEventListener("load", () => {
        // 상태 코드(status)에 따른 성공 실패 구분
        if( request.status == 200 ){    // 상태코드 200이 되어야 성공
            resolve(JSON.parse(request.response))   // 파싱해서 결과를 resolve.
        }else{  
            reject("요청 실패!")
        }
    } )
    request.send()
})


// 프로미스 호출을 버튼 클릭시에 한다
// 성공시에는 img 태그에 이미지를 src 를 지정하게끔 한다


button.addEventListener("click",function(){


    getDog.then((resolveData)=>{
        img.src = resolveData.message
    })


    .catch((rejectedData)=>{
        console.log(rejectedData)
    })
})

 

 

여기까지 프로미스에 대해서 알아보았습니다. 

이 다음에는 클래스 class 에 대해서 알아볼게요.

반응형