LHJ

I'm a FE developer.

14.3.2 프로미스 사용

20 May 2020 » js_lj

14.3.2 프로미스 사용

countdown 함수를 어떻게 사용하는지 알아봅시다.
프로미스는 무시해버리고 countdown(5) 처럼 호출해도 됩니다.
카운트다운은 여전히 동작하고, 무슨 말인지 알기 어려운 프로미스는 신경쓰지 않아도 됩니다.
하지만 프로미스의 장점을 이용하고 싶다면 어떻게 해야 할까요?
반환된 프로미스를 사용하는 예제를 살펴봅시다.

function countdown(seconds) {
    return new Promise(function(resolve, reject) {
        for (let i=seconds; i>=0; i--) {
            setTimeout(function() {
                if (i>0) console.log(i + '...');
                else resolve(console.log("GO!"));
            }, (seconds-i)*1000);
        }   
    })
}

countdown(5).then(
    function() {
        console.log("countdown completed successfully");
    },
    function(err) {
        console.log("countdown experienced an error: " + err.message);
    }
)

이 예제에서는 반환된 프로미스를 변수에 할당하지 않고 then 핸들러를 바로 호출했습니다.
then 핸들러는 성공 콜백과 에러 콜백을 받습니다.
경우의 수는 단 두 가지뿐입니다.
성공 콜백이 실행되거나, 에러 콜백이 실행되거나 입니다.
프로미스는 catch 핸들러도 지원하므로 핸들러를 둘로 나눠서 써도 됩니다.

function countdown(seconds) {
    return new Promise(function(resolve, reject) {
        for (let i=seconds; i>=0; i--) {
            setTimeout(function() {
                if (i>0) console.log(i + '...');
                else resolve(console.log("GO!"));
            }, (seconds-i)*1000);
        }   
    })
}

const p = countdown(5);
p.then(function() {
    console.log("countdown completed successfully");
});
p.catch(function(err) {
    console.log("countdown experienced an error: " + err.message);
})

countdown 함수를 수정해서 에러가 일어나게 만들어 봅시다.
13은 불길한 숫자이니 카운트다운을 하다가 13을 만나면 에러를 내는 겁니다.

function countdown(seconds) {
    return new Promise(function(resolve, reject) {
        for (let i=seconds; i>=0; i--) {
            setTimeout(function() {
                if (i===13) return reject(new Error("Oh my god"));
                if (i>0) console.log(i + '...');
                else resolve(console.log("GO!"));
            }, (seconds-i)*1000)
        }
    })
}

숫자를 바꿔 가면서 몇 번 테스트해 보십시오.
흥미로운 일이 벌어질 겁니다.
물론 13보다 작은 숫자를 사용하면 에러 없이 카운트다운이 실행됩니다.
13 이상의 숫자를 사용하면 13에서 에러가 일어납니다.
하지만 콘솔에는 12부터 다시 카운트를 기록합니다.
reject나 resolve가 함수를 멈추지는 않습니다.
이들은 그저 프로미스의 상태를 관리할 뿐입니다.

countdown 함수는 개선할 부분이 더 있습니다.
일반적으로 함수가 성공이든 실패든 결정됏다면(settled) 멈춰야 하는데 countdown 함수는 실패한 후에도 계속 진행합니다.
앞에서 콘솔에 기록하는 부분이 별로 필요하지 않다는 이야기를 했습니다.
사실 필요한 것은 카운트다운을 컨트롤할 수 있는 기능입니다.

프로미스는 비동기적 작업이 성공 또는 실패하도록 확정하는, 매우 안전하고 잘 정의된 매커니즘을 제공하지만 현재는 진행 상황을 전혀 알려주지 않습니다.
즉 프로미스는 오나료되거나 파기될 분, ‘50% 진행됐다’라는 개념은 아예 없는 겁니다.
진행 상황을 알려준다면 매우 유용할텐데 말입니다.
Q(https://github.com/kriskowal/q) 같은 프로미스 라이브러리에는 진행 상황을 보고하는 기능이 있고, 나중에 언젠가는 이런 기능이 자바스크립트 프로미스에 도입될 수도 있겠지만, 지금 당장은 그런 기능에 기대지 않고 다른 방법을 찾아야 합니다.
이벤트에 대해 알아봐야겠군요.