자바스크립트는 비동기 처리를 위한 하나의 패턴으로 콜백함수를 사용한다.
프로미스는 자바스크립트 비동기 처리에 사용 되는 객체이다.
💡 ES6 : 비동기 함수 호출 또는 비동기 연산이 완료되었을 때, **이후에 처리할 함수나 에러를 처리하기 위한** 함수를 설정하는 모듈(→ 비동기 처리 : 특정 코드의 실행이 완료될때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성)
//Promise의 활용 예
function sendEmail(text, timeout){
return new Promise((resolve, reject) => {
setTimeout(()=> {
resolve(text);
},timeout)
})
}
sendEmail("To. 교수님께 \n 안녕하세요.", 1000).then((text) =>
sendEmail(`${text} oo 올림`, 1000)
).then((text) => {
console.log(`메일 전송완료! 내용: ${text} `);
});
원래는 비동기처리를 위해 콜백함수를 사용했다. 하지만 콜백함수를 사용해서 연속적으로 비동기 로직을 처리하면 콜백 지옥이 발생할 수 있다.
:: 콜백지옥의 예
setTimeout
을 사용해서 3초 후에 콘솔에 아래와같은 문장을 표시하는 함수를 작성해보자.
'How are you/'
'I am fine.'
'Thank you'
'And you?'
setTimeout(() => { // callback1
console.log('How are you/');
setTimeout(function() { // callback2
console.log('I am fine.');
setTimeout(function() { // callback3
console.log('Thank you');
setTimeout(function() { // callback4
console.log('And you?');
}, 3000);
}, 3000);
}, 3000);
}, 3000);
위와 같은 콜백지옥은 다음과 같은 문제점들을 가지고 있다.
프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용한다.
:: 프로미스 사용의 예
function getData(callbackFn){
$.get('url 주소', function(res){
callbackFn(res);
});
}
getData(function(tableData){
console.log(tableData)
});
비동기 처리를 위해 프로미스 대신 콜백 함수를 사용한 통신 코드이다. 이 코드를 promise
를 사용해서 아래 코드처럼 변경할 수 있다.
//Promise 사용
function getData(callbackFn){
//new promise 추가
return new Promise(function(resolve, reject){
$.get('url 주소', function(res){
//데이터를 받으면 resolve() 호출
resolve(res)
});
});
}
// getData()의 실행이 끝나면 호출되는 then()
getData().then(function(tableData){
//resolve()의 결과 값이 여기로 전달됨
console.log(tableData)
});
//프로미스의 생성
const promise = new Promise((resolve, reject) => {
//프로미스 함수의 콜백 함수 내부에서 비동기 처리를 수행한다ㅣ.
if(비동기 처리 성공){
resolve('아싸 성공');
} else {
reject ('실패해쑴 ㅠㅠ');
}
});
Promise 생성자 함수를 new
연산자와 함께 호출하면 Promise 객체가 생성된다.
Promise 생성자 함수는 비동기 처리를 수행할 콜백함수를 인수로 전달받는데, 이 콜백 함수는 resolve
와 reject
함수를 인수로 전달 받는다.
프로미스는 다음과 같이 현재 비동기 처리가 어떻게 진행되고 있는지를 나타내는 상태 정보를 갖는다.
프로미스 상태 정보 | 의미 | 상태 변경 조건 |
---|---|---|
pending (대기) | 비동기 처리가 아직 수행되지 않은 상태 ( = fulfilled도 rejected도 안된 초기 상태) | 프로미스가 생성된 직후 기본 상태 |
fulfilled (이행) | 비동기 처리가 수행된 상태 (성공) | resolve 함수 호출 |
rejected (실패) | 비동기 처리가 수행된 상태 (실패) | reject 함수 호출 |
1️⃣ Pending (대기)
new Promise();
new Promise()
메서드를 호출하면 Pending 상태가 된다. new Promise()
메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve
와 reject
함수를 인수로 전달 받는다.
2️⃣ Fulfilled (이행)
new Promise(function(resolve, reject) {
resolve();
});
콜백 함수의 인자 resolve
를 실행하면 fulfilled 상태가 된다.
:: 사용 예
function getData() {
return new Promise(function(resolve, reject) {
let data = 100;
resolve(data);
});
}
// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function(resolvedData) {
console.log(resolvedData); // 100
});
3️⃣ Rejected (실패)
new Promise(function(resolve, reject) {
reject();
});
콜백 함수의 인자 reject
를 실행하면 rejected 상태가 된다. 그리고 실패 상태가 되면 실패한 이유를 catch()
로 받을 수 있다.
:: 사용 예
function getData() {
return new Promise(function(resolve, reject) {
reject(new Error("Request is failed"));
});
}
// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function(err) {
console.log(err); // Error: Request is failed
});
콜백 패턴은 에러 처리가 곤란하다는 문제가 있는데 프로미스는 에러를 문제없이 처리할 수 있다. 비동기 처리에 대한 후속처리는 프로미스가 제공하는 후속 처리 메서드를 사용한다.
프로미스의 비동기 처리 상태가 변화하면 이에 따른 후속 처리를 해야 한다. 이를 위해 프로미스는 후속 메서드 then
, catch
, finally
를 제공한다.
then
, catch
메소드는 Promise 객체를 반환하므로 chaining 형태로 사용될 수 있다.
1️⃣ then
then 메서드는 두 개의 콜백 함수를 인수로 전달받는다.
const wrongURL = 'http ~~~ 잘못된 주소';
promiseGet(wrongURL)
.then(res => console.log(res))
.then(err => console.log(err))
2️⃣ catch
catch 메서드는 한 개의 콜백 함수를 인수로 전달받고, 프로미스가 rejected 상태인 경우에만 호출된다.
promiseGet('http ~~~ 올바른 주소')
.then(res => console.log(res))
.catch(err => console.log(err)
catch 메서드를 사용하는 것이 가독성이 좋고 명확하다.
3️⃣ finally
finally 메서드는 한 개의 콜백 함수를 인수로 전달받고, 프로미스의 fulfilled 또는 rejected와 상관없이 무조건 한 번 호출된다.
상태와 상관없이 공통적으로 수행해야 할 처리 내용이 있을 때 유용하다.
:: 에러 처리의 예
function getData() {
return new Promise(function(resolve, reject) {
$.get('url 주소/products/1', function(response) {
if (response) {
resolve(response);
}
reject(new Error("Request is failed"));
});
});
}
// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getData().then(function(data) {
console.log(data); // response 값 출력
}).catch(function(err) {
console.error(err); // Error 출력
});
참고 : 캡틴판교 / 자바스크립트 딥다이브