JS

JS 이벤트 처리 - Promise

ryeonng 2024. 8. 2. 16:31

 

Promise 타입

자바스크립트 Promise는 비동기 작업을 처리하기 위한 객체이다. Promise는 어떤 작업의 결과를 반환하는 객체로서, 이를 통해 비동기적으로 실행되는 작업을 처리하고 그 결과를 콜백 함수 등을 이용해 처리할 수 있다.

 

Promise는 총 세가지 상태를 갖는다.

 

  1. 대기(pending) : Promise 객체가 생성되었으나 아직 처리가 진행되지 않은 상태
  2. 이행(fulfilled) : Promise 객체가 처리를 완료하여 결과를 반환한 상태
  3. 거부(rejected) : Promise 객체가 처리를 실패하였거나 오류가 발생한 상태
웹 브라우저 안에 자바스크립트 엔진은 싱글 스레드로 동작하며, 이벤트 루프를 통해 비동기 작업을 처리한다.

 

 

사전 기반 지식 - 자바스크립트 엔진(v8)

JS 엔진 내부만 보면 크게 Memory Heap & Call stack 2개의 파트가 있다.

 

Memory Heap

  • 데이터를 임시 저장하는 곳으로, 함수나 변수, 함수를 실행할 때 사용하는 값들을 저장한다. heap 저장공간을 떠올리면 된다.
  • 해당 부분에서 이제 더 이상 사용되지 않는 변수나 데이터 덩어리를 비워주는 GC(Garbage Collection)가 있다.

Call stack

  • 코드가 실행되면 순서를 기록해 놓고, 하나씩 순차적으로 꺼내 실제로 실행할 수 있도록 도와주는 공간. stack 자료구조 형태이며 Last In, First Out (LIFO) 원칙을 따른다.

 

Promise 타입 선언과 활용

 

첫 번째 소화시키는 방법 살펴보기

async/await 사용 방식
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onclick="runOrderCoffee1('아메리카노')">Promise Callback Test</button>

    <script>
        // 커피를 주문하고 만드는 가상의 비동기 함수 선언
        // 항상 Promise 타입을 반환한다. (객체를 반환)
        function orderCoffee(order) {
            return new Promise(function(resolve,reject) {
                // 기존에 제공하는 setTimeout API 활용
                setTimeout(function() {
                    if(order === "아메리카노") {
                        resolve("아메리카노가 나왔습니다.");
                    } else if(order === "라떼") {
                        resolve("라떼가 나왔습니다.");
                    } else {
                        reject("죄송합니다. 오늘 재료가 모두 소진되었습니다.");
                    }
                },2000); // 2초 뒤에 return (동작)
            });
        }

        // Promise 타입을 소화시키는 방법 - 1
        // 'async' 키워드와 await 를 사용하여 비동기식 코드를 동기식 방법으로 간결하게 소화시킬 수 있다.
        // ※주의 - 돌아가는 방식은 비동기적 방식이다.
        async function runOrderCoffee1(order) {
            console.log("start .....................");
            try {
                const result = await orderCoffee(order);
                console.log(result);
            } catch(error) {
                console.log(error);
            }
            console.log("end .....................");
        }




    </script>
</body>
</html>

 

resolve와 reject란

resolve와 reject는 Promise의 생성자 함수 내부에서 제공되는 콜백 함수의 매개변수이다.
각각의 매개변수는 특정 함수를 나타내며, 이 함수들을 호출함으로써 Promise의 상태를 변경할 수 있다.

resolve :
resolve는 함수 타입의 매개변수이다.
resolve 함수가 호출되면, 해당 Promise의 상태는 **pending(대기)**에서 **fulfilled(이행)**으로 변경된다.
resolve 함수에 전달된 값은 Promise의 결과 값이 된다. 이 값은 .then() 메서드의 첫 번째 콜백 함수로 전달된다.
예: 위의 코드에서 "아메리카노가 나왔습니다" 또는 "라떼가 나왔습니다"는 .then()에서 받을 수 있는 값이다.

reject :
reject 역시 함수 타입의 매개변수이다.
reject 함수가 호출되면, 해당 Promise의 상태는 **pending(대기)**에서 **rejected(거부)**로 변경된다.
reject 함수에 전달된 값은 Promise의 거부 이유가 된다. 이 값은 .catch() 메서드 또는 .then()의 두 번째 콜백 함수로 전달될 수 있다.
예: 위의 코드에서 "죄송합니다 오늘 재료가 모두 소진 되었습니다"는 .catch()나 .then()의 두 번째 콜백에서 받을 수 있는 값이다.
이렇게 resolve와 reject를 사용하면 비동기 작업의 결과나 오류를 알릴 수 있으며, 이에 따라 후속 처리를 진행할 수 있다.

 

명시적 체인 (Explicit Changing) 사용 방법
then, catch, finally 메서드를 통해 콜백 함수를 체인으로 연결하는 방식

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onclick="runOrderCoffee2('소주')">Promise Callback Test</button>

    <script>
        // 커피를 주문하고 만드는 가상의 비동기 함수 선언
        // 항상 Promise 타입을 반환한다. (객체를 반환)
        function orderCoffee(order) {
            return new Promise(function(resolve,reject) {
                // 기존에 제공하는 setTimeout API 활용
                setTimeout(function() {
                    if(order === "아메리카노") {
                        resolve("아메리카노가 나왔습니다.");
                    } else if(order === "라떼") {
                        resolve("라떼가 나왔습니다.");
                    } else {
                        reject("죄송합니다. 오늘 재료가 모두 소진되었습니다.");
                    }
                },2000); // 2초 뒤에 return (동작)
            });
        }

        // Promise 타입을 소화시키는 방법 - 1
        // 'async' 키워드와 await 를 사용하여 비동기식 코드를 동기식 방법으로 간결하게 소화시킬 수 있다.
        // ※주의 - 돌아가는 방식은 비동기적 방식이다.
        async function runOrderCoffee1(order) {
            console.log("start .....................");
            try {
                const result = await orderCoffee(order);
                console.log(result);
            } catch(error) {
                console.log(error);
            }
            console.log("end .....................");
        }

        // 소화시키는 방법 - 2 : then()과 catch() 메서드 활용
        function runOrderCoffee2(order) {
            console.log("start .....................");

            orderCoffee(order)
            .then((message) => {
                console.log(message);
            })
            .catch((error) => {
                console.log(error);
            });
            console.log("end .....................");
        }



    </script>
</body>
</html>