Node

[Node.js] 프로미스(Promise)에 대하여 알아보기

YaluStar 2023. 2. 9. 17:31

안녕하세요.

이번에는 Promise(프로미스)에 대하여 알아보겠습니다.

 

 

1. 프로미스(Promise)

  • Callback Hell 로 인한 복잡도 증가와 예외처리의 어려움을 해결하기 위해 만들어진 것
  • 비동기 작업에서 성공과 실패를 분리해 메소드를 수행한다.
  • resolve(value) : 일이 성공적으로 끝난 경우 프로미스를 실행한 곳의 then으로 들어간다.
  • reject(error) : 에러 발생 시 프로미스를 실행한 곳의 catch로 들어간다.

 

2. 프로미스 상태

  • Pending
    • Promse를 수행 중인 상태
  • Fulfilled
    • Promise가 resolve 된 상태
  • Rejected
    • Promise가 지켜지지 못한 상태
  • Settled
    • fulfilled 혹은 rejected로 결론이 난 상태

 

코드 작성 방법

new Promise(function(resolve, reject) {
    resolve : 함수형태, 성공했을 때 실행할 친구
    reject : 함수형태, 실패 or 에러를 처리할 때 사용되는 친구
});

 

먼저 func1() 함수내에 Promise를 설정하는 방법입니다.

return new Promise를 사용하며, 인자 값으로 함수를 설정합니다.

나중에 실행되는 함수에는 resolve, reject 인자 값이 기본 값으로 들어간다고 생각하시면 됩니다.

정상 실행되면 resolve가 되고 err 발생시 reject가 사용됩니다.

function func1() {
    return new Promise(function(resolve, reject) {
        resolve('성공');
    });
}

var a = func1();
console.log(a);

 

  • .then 사용해보기
function func1() {
    return new Promise(function(resolve, reject) {
        resolve('성공');
    });
}

func1()
.then(function(result) {
    console.log('result : ', result);
});

 

.then 명령어가 func1 함수가 resolve 값을 넘겨줄 때까지 기다렸다가 다음 함수를 실행시킨다. 이 때 resolve로 받은 인자 값은 다음 함수에 전달해주며 result = '값'으로 사용된다.

 

이번에는 func2() 함수 내에 비동기 함수를 추가했습니다.

함수를 실행해서 결과를 확인해봅니다.

function func2() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {resolve('성공');}, 1000);
    });
}

func2()
.then(function(result) {
    console.log('result2 : ', result);
});

 

결과가 정상적으로 출력이 되었습니다.

Promise는 자체적으로 함수가 종료될 때까지 기다린 후에 값을 넘기기 때문에, 비동기 함수를 사용해도 이상없이 값을 전달하고 출력할 수 있습니다.

 

then 함수는 1개만 사용할 수 있는 것이 아니라 여러 개도 사용이 가능하며,

1번 then이 끝나면 2번 then이 실행되는 방식입니다.

.then 사용 방법에 따라서 함수 return으로 값을 넘겨주는 경우도 있습니다

function func2() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {resolve('성공');}, 1000);
    });
}

func2()
.then(function(result) {
    console.log('result3 : ', result);
    return 'a';
}).then(function(abc) {
    console.log('abc : ', abc);
});

 

그래서 처음에 받은 resolve(’성공’)을 받아서 result에 출력이 되고 return ‘a’로 값을 넘겨서

abc : a 라는 메시지를 출력하는 것을 볼 수 있습니다.

 

  • reject 처리

func3 함수에서 flag 값을 받아서 각각 resolve, reject를 실행하고 있습니다.

여기서 resolve ⇒ then, reject ⇒ catch 로 넘어가게 되지만 이렇게 사용할 수 도 있습니다.

then안에 함수를 2개로 나누어 줍니다.

그러면 resolve 일 때는 1번 함수가 실행되고, reject 일 때는 2번 함수가 실행됩니다.

function func3(flag) {
    return new Promise(function(resolve, reject) {
        if (flag) {
            resolve('flage는 true');
        } else {
            reject('flage는 flase');
        }
    });
}

// then 안에 1번 함수(resolve), 2번 함수(reject)로 나눠서 쓰는 방법이 있다.
func3(false).then(
    function(msg) {
        console.log('msg1 : ', msg);
    },
    function(msg) {
        console.log('msg2 : ', msg)
    }
);

func3(true).then(
    function(msg) {
        console.log('msg1 : ', msg);
    },
    function(msg) {
        console.log('msg2 : ', msg)
    }
);

 

  • catch

보통은 then을 2개의 함수로 나누어서 작성하기 보다는 catch 함수를 사용해서 reject를 처리합니다.

여기서는 func3이 false 값을 받아서 reject 함수가 실행되서 catch가 실행되었습니다.

function func3(flag) {
    return new Promise(function(resolve, reject) {
        if (flag) {
            resolve('flage는 true');
        } else {
            reject('flage는 flase');
        }
    });
}

// then 안에 (resolve)만 작성하고, catch(rejcet) 를 나눠서 작성하는 방법
func3(false).then(
    function(msg) {
        console.log('msg1 : ', msg);
    },
).catch(
    function(msg) {
        console.log('msg2 : ', msg)
    }
);

 

  • then 2개 + catch

그런데 then을 2개로 나누어서 작성하고 catch까지 작성을 하면 어떻게 되는지 확인해보겠습니다.

function func3(flag) {
    return new Promise(function(resolve, reject) {
        if (flag) {
            resolve('flage는 true');
        } else {
            reject('flage는 flase');
        }
    });
}

func3(false).then(
    function(msg) {
        console.log('msg1 : ', msg);
    },
    function(msg) {
        console.log('msg2 : ', msg)
    }
).catch(
    function(msg) {
        console.log('msg3 : ', msg)
    }
);

then 안에 1번(resolve), 2번(reject) 둘다 있고, catch(rejcet) 까지 있는 경우에 reject는 then의 2번에서 처리가 되어 msg2 만 출력이 되고 catch는 실행이 되지 않습니다.

 

 

실습코드

더보기

callback 함수를 promise로 변경하기

 

 

callback 함수 작성 코드

function login(id, pw, cb) {
    setTimeout(() => {
        console.log('사용자');
        cb(id); // 콜백 함수
    }, 3000);
}
function getVideo(id, cb) {
    setTimeout(function() {
        console.log(id + '의 비디오 리스트');
        cb( ['아바타', '라라랜드']);
    }, 2000);
}
function getDetail(video, cb) {
    setTimeout(() => {
        cb('비디오 제목 : ' + video);
    }, 1000);
}

// 콜백 함수를 이용한 순서 강제 설정
login('kim', '1234', function(user) {
    // console.log(user);
    getVideo(user, function(videos) {
        console.log('videos : ', videos);
        getDetail(videos[0], function(msg) {
            console.log(msg);
        });
    });
});

 

promise

function login(id, pw) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('사용자 입장');
            resolve(id);
        }, 3000);
    });
}

function getVideo(id) {
    return new Promise(function(resolve, rejcet) {
        setTimeout(function() {
            console.log(id + '의 비디오 리스트');
            resolve(['아바타', '라라랜드']);
        }, 2000);
    });
}

function getDetail(videos) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(videos[0]);
        }, 1000);
    });
}

login('kim', '1234')
.then(function(id) {
    console.log('user : ', id);
    return getVideo(id);
})
.then(function(videos) {
    console.log('videos : ', videos);
    return getDetail(videos);
})
.then(function(video) {
    console.log('비디오 제목 : ' + video);
});



// 이런식으로도 사용 가능
// 이 경우에 resolve 값을 바로 함수에 전달해줌
// login('kim', '1234')
// .then(getVideo)
// .then(getDetail)
// .then(function(video) {
//     console.log('비디오 제목 : ' + video);
// });

 

이상으로 Promise(프로미스)에 대하여 알아보았습니다.

감사합니다.

반응형