100log

About

Javascript - Promise

Javascript

Javascript - Promise

Promise란?

Promise의 3가지 상태(states)

chaining

then

catch

finally

callback hell에서 벗어나기

Promise.all

Promise.race

main-img

Javascript - Promise

Promise란?

Promise는 자바스크립트 비동기 처리에 사용되는 객체다.
자바스크립트의 비동기 처리란 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성을 의미한다.

const pr = new Promise((resolve, reject) => {
    // code
})

new Promise로 생성하며 인수로 함수를 전달 받는데 resolve는 성공, reject는 실패했을 때 실행되는 함수다. 이를 callback함수라고 한다.


Promise의 3가지 상태(states)

Promise의 상태란 처리 과정을 의미하며 생성에서 종료까지 3가지 상태를 갖는다.

  • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태로 result는 undefined이다.
  • Fulfilled(이행) : 비동기 처리가 완료되어 resolve를 호출하면 Fulfilled가 된다. 이때 result는 resolve 함수로 전달된 값이다.
  • Rejected(실패) : 비동기 처리가 실패하면 즉 reject가 호출되면 Rejected가 되며 result는 reject로 전달된 error이다.

chaining

then

then을 이용하여 resolve와 reject를 처리할 수 있다.

const pr = new Promise((resolve, reject) => {

    let isTrue = true;

    setTimeout(() => {
        if(isTrue){

            resolve('success');
        }else{
            reject('fail');
        }
    }, 3000)
});

pr.then(
    function(result){ // 이행 되었을때
        console.log(result); // 'success'
    },
    function(err){ // 거부 되었을때
        console.log(err); // 'fail'
    }
);

catch

catch는 reject인 경우에만 실행된다.
catch문을 사용하면 가독성도 더 좋고 첫 번째 함수를 실행했을때 나오는 error를 잡아줄 수 도 있으니 사용하는 것이 더 좋다.

pr.then(
    function(result){ 
        console.log(result);
    }
).catch(
    function(err){
        console.log(err);
    };
);

finally

finally는 이행이든 거부든 처리가 완료되면 항상 실행된다.
로딩 화면 같은 것을 없앨 때 유용하다.

pr.then(
    function(result){ 
        console.log(result);
    }
).catch(
    function(err){
        console.log(err);
    }
).finally(
    function(){
        console.log('end');
    }
);
// 'success'
// 'end'

callback hell에서 벗어나기

아래와 같이 1,2,3번 함수를 실행하는 로직을 Promise를 사용하지 않고 구현 한다면 로직이 추가될수록 뎁스가 깊어지면서 callback hell, 콜백 지옥에 빠지게 된다.

const fn1 = (callback) => {
    setTimeout(() => {
        console.log('1번 함수 실행');
        callback();
    }, 3000)
};

const fn2 = (callback) => {
    setTimeout(() => {
        console.log('2번 함수 실행');
        callback();
    }, 6000)
};

const fn3 = (callback) => {
    setTimeout(() => {
        console.log('3번 함수 실행');
        callback();
    }, 2000)
};



console.log('start');
console.time('time-check');

fn1(function(){
    fn2(function(){
        fn3(function(){
            console.log('end');
            console.timeEnd('time-check');
        })
    })
});
// start, 1번 함수 실행, 2번 함수 실행, 3번 함수 실행, end
// time-check: 11027.3369140625 ms

Promise를 사용하여 구현해보자.
아래와 같이 Promise들이 연결되는 것을 Promise chaining이라 한다.

const fn1 = () => {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('1번 함수 실행');
        },3000);
    });
};

const fn2 = (msg) => {
    console.log(msg);
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('2번 함수 실행');
        },6000);
    });
};

const fn3 = (msg) => {
    console.log(msg);
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('3번 함수 실행');
        },2000);
    });
};

console.log('start');
console.time('time-check');

fn1()
    .then((result) => fn2(result))
    .then((result) => fn3(result))
    .then((result) => console.log(result))
    .catch((err) => console.log(err))
    .finally(() => {
        console.log('end');
        console.timeEnd('time-check');
    });
// start, 1번 함수 실행, 2번 함수 실행, 3번 함수 실행, end
// time-check: 11042.4560546875 ms

Promise.all

Promise.all은 여러개의 Promise들을 비동기적으로 실행하여 처리 할 수 있으며, 하나의 Promise라도 reject를 반환하거나 오류가 날 경우 모든 Promise들을 reject 처리한다.
하나의 정보라도 누락될 경우 화면을 보여줘서는 안될 때 사용하곤 한다.

const fn1 = () => {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('1번 함수 실행');
        },3000);
    });
};

const fn2 = (msg) => {
    console.log(msg);
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('2번 함수 실행');
        },6000);
    });
};

const fn3 = (msg) => {
    console.log(msg);
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('3번 함수 실행');
        },2000);
    });
};

console.log('start');
console.time('time-check');

Promise.all([fn1(), fn2(), fn3()]).then((res, rej) => {
    console.log(res);
})
.catch((err) => console.log(err))
.finally(() => console.timeEnd('time-check'));
// ['1번 함수 실행', '2번 함수 실행', '3번 함수 실행']
// time-check: 6007.13916015625 ms

Promise.race

Promise.race는 하나의 Promise라도 1등으로 완료되면 종료된다.
용량이 큰 이미지들을 로딩하는데 그중 하나라도 완료되면 그 이미지를 보여줄 때 사용하면된다.

const fn1 = () => {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('1번 함수 실행');
        },3000);
    });
};

const fn2 = (msg) => {
    console.log(msg);
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('2번 함수 실행');
        },6000);
    });
};

const fn3 = (msg) => {
    console.log(msg);
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('3번 함수 실행');
        },2000);
    });
};

console.log('start');
console.time('time-check');

Promise.race([fn1(), fn2(), fn3()]).then((res, rej) => {
    console.log(res);
})
.catch((err) => console.log(err))
.finally(() => console.timeEnd('time-check'));
// 3번 함수 실행
// time-check: 2009.635986328125 ms
profile_img백종민
1993
Seoul
커리어 발전을 위한 새로운 기회를 찾고있습니다.