Promise

상점에 들어가서 상품을 주문했을 때 언제 어떻게 나올지 모르는 상품을 기다릴 때 사용한다.

완성 혹은 실패했을 때 연락이 오게 만드는 함수

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

인수는 resolve와 reject이다.
resolve는 성공한 경우
reject는 실패한 경우
이렇게 어떤 일이 완료된 이후 실행되는 함수를 callback함수라고 한다.

  1. new Promise 생성자가 반환하는 promise 객체는 state와 result를 프로퍼티로 갖는다.
  2. state는 초기 pending(대기) 상태이고 result는 undefined이며, resolve(value)가 호출되면 state는 fulfilled가 된다.
  3. 이때 result는 resolve함수가 전달된 값(value)이다.
  4. 만약 실패하면 state는 rejected가되고 result는 reject함수로 전달된 error이다.


판매자의 코드

성공

const pr = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 3000);
});

state: pending / result: undefined
3초 후
state: fulfilled/ result: ‘OK’

실패

const pr = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('error..');
    }, 3000);
});

state: pending / result: undefined
3초 후
state: rejected/ result: ‘error’


소비자의 코드

const pr = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 3000)
});

// 여기부터 소비자의 코드

pr.then(
    function(result){
        console.log(result + ' 가지러 가자.');
    },
    function(err){
        console.log('다시 만들어주세요.');
    }
);

첫번째 인수는 promise가 이행되었을 때 실행되고 result에는 OK가 들어옴

두번째 인수는 promise가 거부되었을 때 실행되고 err에는 에러 값이 들어온다.

resolve로 실행되었기 때문에 두번째 callback을 실행되지 않는다.


catch

reject일 때만 실행된다.

const pr = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 3000);
});

pr.then(
    function(result){
        console.log(result + ' 가지러 가자.');
    }
).catch(
    function(err){
        console.log('다시 만들어주세요.');
    }
);

catch로 명확하게 구분하는 것이 가독성에도 좋고 첫번째 함수를 실행했다가 나는 에러도 잡아줄 수 있다.


finally

이행이든 거부든 처리가 완료되면 항상 실행된다.

const pr = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 3000);
});

pr.then(
    function(result){
        console.log(result + ' 가지러 가자.');
    }
).catch(
    function(err){
        console.log('다시 만들어주세요.');
    }
).finally(
    function(){
        console.log('---주문 끝---');
    }
);


예문

const pr = new Promise((resolve, reject) => { setTimeout(() => {
    resolve("OK");
}, 1000);
});

console.log("시작");

pr.then((result) => {
    console.log(result);
}).catch((err) => {
    console.log(err);
}).finally(() => {
    console.log("");
});

시작
1초후
OK / reject라면 Error: error…


3개의 상품, promise 사용 X

const f1 = (callback) => {
    setTimeout(() => {
        console.log("1번 주문완료");
    }, 1000);
};

const f2 = (callback) => {
    setTimeout(() => {
        console.log("2번 주문완료");
    }, 2000);
};

const f3 = (callback) => {
    setTimeout(() => {
        console.log("3번 주문완료");
    }, 3000);
};

console.log('시작');
f1(() => {
    f2(() => {
        f3(() => {
            console.log('');
        });
    });
});

이렇게 뎁스가 깊어지면서 계속 callback을 호출하는 것을 callback hell이라고 한다.


3개의 상품, promise 사용

const p1 = () => {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("1번 주문 완료");
        }, 1000);
    });
}

const p2 = (message) => {
    console.log(message)
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("2번 주문 완료");
        }, 2000);
    });
}

const p3 = (message) => {
    console.log(message)
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("3번 주문 완료");
        }, 3000);
    });
}

console.log('시작');

p1()
.then((res) => p2(res))
.then((res) => p3(res))
.then((res) => console.log(res));
.catch(console.log)
.finally(() => {
    console.log('');
});

promise가 연결되어 있는 것을 promise chaining이라고 한다.


2번 실패 예문

const p1 = () => {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("1번 주문 완료");
        }, 1000);
    });
}

const p2 = (message) => {
    console.log(message)
    return new Promise((res, rej) => {
        setTimeout(() => {
            rej("2번 주문 실패");
        }, 2000);
    });
}

const p3 = (message) => {
    console.log(message)
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("3번 주문 완료");
        }, 3000);
    });
}

console.log('시작');

p1()
.then((res) => p2(res))
.then((res) => p3(res))
.then((res) => console.log(res));
.catch(console.log)
.finally(() => {
    console.log('');
});

시작
1번 주문 완료
2번 주문 실패


promise.all

한번에 주문하고 가장 오래걸리는 상품의 시간이 지나면 모든 제품을 받을 수 있다.

const p1 = () => {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("1번 주문 완료");
        }, 1000);
    });
}

const p2 = (message) => {
    console.log(message)
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("2번 주문 성공");
        }, 2000);
    });
}

const p3 = (message) => {
    console.log(message)
    return new Promise((res, rej) => {
        setTimeout(() => {
            res("3번 주문 완료");
        }, 3000);
    });
}

console.time("x"); // 시간을 재는 방법
Promise.all([p1(), p2(), p3()]).then((res) => {
    console.log(res);
    console.timeEnd("x");
});

하지만 실패하면 어떠한 데이터도 얻을 수 없다.
따라서 정보 하나라도 누락되면 페이지를 보여주면 안되는 경우에 사용할 수 있다.


promise.race

하나라도 완료되면 멈춘다.

console.time("x"); // 시간을 재는 방법
Promise.all([p1(), p2(), p3()]).then((res) => {
    console.log(res);
    console.timeEnd("x");
});

1번이 완료되면 멈춘다.

용량이 큰 이미지들을 로딩할 때 하나라도 완료되면 이미지를 보여 줄 때

댓글남기기