본문 바로가기
강의 실습/한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

Promise - 콜백 지옥에서 탈출하기

by Jint 2023. 12. 24.

콜백지옥에서 우리를 구원하다.

Promise : 자바스크립트의 비동기를 돕는 객체. 비동기 처리 결과값을 핸들링하는 코드를 비동기 함수로부터 분리할 수 있다.

- 비동기 작업이 가질 수 있는 3가지 상태
Pending(대기 상태) : 현재 비동기 작업이 진행중이거나, 작업이 시작할 수도 없는 문제가 발생했음을 의미
Fulfilled(성공) : 비동기 작업이 의도한대로 정상적으로 완료된 상태
Rejected(실패) : 비동기 작업이 실패했음 (사례 : 서버 응답하지 않음, 시간이 오래걸려 자동으로 취소됨)
Pending → Fulfilled : resolve(해결)
Pending → Rejected : reject(거부)

1. Promise 객체 사용

// 2초뒤 전달 받은 값이 양수인지 음수인지 판단하는 비동기 작업
// Callback을 이용한 비동기 처리
function isPositive(number, resolve, reject) {
    setTimeout(() => {
        if (typeof number === "number") {
            // 성공 -> resolve
            resolve(number >= ? "양수" : "음수");
        } else {
            // 실패 -> reject
            reject("주어진 값이 숫자형 값이 아닙니다");
        }
    }, 2000);
}

isPositive(
    10 // []
  , (res) => {
        console.log("성공적으로 수행됨 : ", res);
    }
  , (err) => {
        console.log("실패 하였음 : ", err);
    }
);
/*
- 콘솔
- 값 : 10
성공적으로 수행됨 : 양수
- 값 : []
실패 하였음 : 주어진 값이 숫자형 값이 아닙니다
*/

// Promise를 이용한 비동기 처리
function isPositiveP(number) {
    const executor = (resolve, reject) => { // 실행자
        setTimeout(() => {
            if (typeof number === "number") {
                // 성공 -> resolve
                console.log(number);
                resolve(number >= ? "양수" : "음수");
            } else {
                // 실패 -> reject
                reject("주어진 값이 숫자형 값이 아닙니다");
            }
        }, 2000);
    }

    const asyncTask = new Promise(executor);
    return asyncTask;
}

const res = isPositiveP(101);

res.then((res) => {
    console.log("작업 성공 : ", res);
}).catch((err) => {
    console.log("작업 실패 : ", err)
});
/*
- 콘솔
- 값 : 10
101
작업 성공 : 양수
- 값 : []
작업 실패 : 주어진 값이 숫자형 값이 아닙니다
*/


어떤 함수가 Promise를 반환한다는 것은, 이 함수가 비동기 작업을 하고 작업 결과를 Promise 객체로 반환받아서 사용할 수 있는 함수라는 것을 의미한다.

2. 콜백 지옥 탈출

// 콜백 지옥
function taskA(a, b, cb) {
    setTimeout(() => {
        const res = a + b;
        cb(res);
    }, 3000);
}
function taskB(a, cb) {
    setTimeout(() => {
        const res = a * 2;
        cb(res);
    }, 1000);
}
function taskC(a, cb) {
    setTimeout(() => {
        const res = a * -1;
        cb(res);
    }, 2000);
}

taskA(3, 4, (a_res) => {
    console.log("task A : ", a_res);
    taskB(a_res, (b_res) => {
        console.log("task B : ", b_res);
        taskC(b_res, (c_res) => {
            console.log("task C : ", c_res);
        });
    });
});
/*
- 콘솔
task A : 7
task B : 14
task C : -14
*/

// Promise 사용
function taskA(a, b) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const res = a + b;
            resolve(res);
        }, 3000);
    });
}
function taskB(a) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const res = a * 2;
            resolve(res);
        }, 1000);
    });
}
function taskC(a) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const res = a * -1;
            resolve(res);
        }, 2000);
    });
}

// 다시 콜백 지옥..?
taskA(5, 1).then((a_res) => {
    console.log("A RESULT : ", a_res);
    taskB(a_res).then((b_res) => {
        console.log("B RESULT : ", b_res);
        taskC(b_res).then((c_res) => {
            console.log("C RESULT : ", c_res);
        });
    });
});
/*
- 콘솔
A RESULT : 6
B RESULT : 12
C RESULT : -12
*/

// then 체이닝
taskA(5, 1).then((a_res) => {
    console.log("A RESULT : ", a_res);
    return taskB(a_res);
}).then((b_res) => {
    console.log("B RESULT : ", b_res);
    return taskC(b_res);
}).then((c_res) => {
    console.log("C RESULT : ", c_res);
});
/*
- 콘솔
A RESULT : 6
B RESULT : 12
C RESULT : -12
*/

// then 체이닝 사이 다른 작업 활용 가능
const bPromiseResult = taskA(5, 1).then((a_res) => {
    console.log("A RESULT : ", a_res);
    return taskB(a_res);
});

console.log("다른 작업1");
console.log("다른 작업2");
console.log("다른 작업3");

bPromiseResult.then((b_res) => {
    console.log("B RESULT : ", b_res);
    return taskC(b_res);
}).then((c_res) => {
    console.log("C RESULT : ", c_res);
});
/*
- 콘솔
다른 작업1
다른 작업2
다른 작업3
A RESULT : 6
B RESULT : 12
C RESULT : -12
*/


Promise 객체를 이용하면 비동기 처리를 호출하는 코드와 결과를 처리하는 코드를 분리할 수 있어서, 콜백 지옥을 피하고 가독성있고 깔끔한 비동기 처리를 할 수 있도록 도와준다.


참고강의 : https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%EB%A6%AC%EC%95%A1%ED%8A%B8#

 

한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 강의 - 인프런

개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, 리액트, 한 강의로 끝장낼 수 있어요.

www.inflearn.com

댓글