반응형
해당 글은 Promise를 사용하기 이전에 callback 함수를 사용할 때와의 비교 및 Promise에 대한 이해 그리고 Promise의 요청 상태에 대해서 이해하기 위한 글입니다
1) Promise를 사용하기 이전 비동기 처리 방식
💡 해당 Promise는 이전에 비동기 통신을 할 때 사용되는 '콜백 함수'의 단점을 보완하기 위해서 추가가 되었으며 아래는 Promise 객체가 생겨나게 된 이전 콜백 함수의 문제점입니다.
1. 콜백 함수(Callback)
💡 콜백 함수(Callback)
- 특정 함수 내 인자로 다른 함수를 받아서 어떤 이벤트나 특정 시점에 도달하였을 때, 시스템에서 인자로 받은 함수를 호출하는 것을 의미합니다.
💡 콜백 함수의 문제점
1. 콜백 패턴을 사용하여 처리 순서를 보장하기 위해 중첩으로 인한 복잡도가 증가하였습니다.
- 비동기 통신 → 요청 → 응답 → 콜백 함수 수행 → 요청 → 응답 → 콜백함수 수행으로 발생하는 '무한 반복 콜백 현상'이 발생하였습니다.
2. 에러가 발생하였을때 어떤 구문에서 에러의 위치를 찾기 어렵다라는 문제점을 가지고 있습니다.
3. 예외처리를 하는데 있어서 어렵다는 문제점을 가지고 있습니다.
[적용 예시] 무한 반복 콜백 현상
// 1초마다 숫자에 10을 더해준다.
const _number10Add = (num, callback) => {
setTimeout(() => {
callback(num + 10);
}, 1000);
};
// 1초마다 숫자에 20을 더해준다.
const _number20Add = (num, callback) => {
setTimeout(() => {
callback(num + 20);
}, 1000);
};
// 1초마다 숫자에 30을 더해준다.
const _number30Add = (num, callback) => {
setTimeout(() => {
callback(num + 30);
}, 1000);
};
// 결과값을 콘솔에 출력한다.
const _numberLog = (number) =>
new Promise(() => {
setTimeout(() => console.log(number), 1000);
});
// 최종 연산 값을 출력한다. => 반복 콜백 문제 발생
const resultConsole = () => {
_number10Add(0, (callbackNum1) => {
_number20Add(callbackNum1, (callbackNum2) => {
_number30Add(callbackNum2, (callbackNum3) => {
_numberLog(callbackNum3);
});
});
});
};
resultConsole();
2) Promise란 무엇인가?
💡 Promise
- ES6에 추가된 문법으로 콜백함수의 단점을 보안하기 위해 등장하였으며 비동기 작업이 수행되어 결과를 반환하는 객체를 의미하며 완료되면 resolve 메소드를 호출하고 작업이 실패하면 reject를 호출하는 함수를 의미합니다.
[더 알아보기]
💡 비동기(Asynchrous) 처리 방식이란?
- 어떠한 데이터 통신을 위해 ‘요청’을 하였을 때, 어떠한 요청에 대한 ‘응답'을 기다리지 않고 다음 코드가 수행되는 처리방식을 의미한다
ex) 하나의 함수를 수행시키는데 A라는 데이터 통신 요청과 B라는 데이터 통신 요청을 수행하는 경우, 순차적으로 A가 수행되고 B가 수행되는 과정이 아닌 A가 요청을 하고 응답을 기다리지 않고 B의 요청이 수행되는 처리 방식을 의미한다.
💡 동기(Synchronous) 처리 방식이란?
- 어떠한 데이터 통신을 위해 ‘요청'을 하였을 때, 어떠한 요청에 대한 ‘응답'을 받을 때까지 기다리다가 완료된 뒤 다음 코드가 수행되는 처리방식을 의미한다.
ex) 하나의 함수를 수행시키는데 A라는 데이터 통신 요청과 B라는 데이터 통신 요청을 수행하는 경우, 순차적으로 A의 요청에 대한 응답을 기다린 뒤 성공적으로 받으면 B의 요청을 수행하는 순차적인 수행을 하는 처리 방식을 의미한다.
[적용 예시] Promise 함수로 변경한 상태 예시
// 1초마다 숫자에 10을 더해준다.
const _number10Add = (num) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(num + 10);
}, 1000);
});
};
// 1초마다 숫자에 20을 더해준다.
const _number20Add = (num) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(num + 20);
}, 1000);
});
};
// 1초마다 숫자에 30을 더해준다.
const _number30Add = (num) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(num + 30);
}, 1000);
});
};
// 결과값을 콘솔에 출력한다.
const _numberLog = (number) =>
new Promise(() => {
setTimeout(() => console.log(number), 1000);
});
// 최종 연산 값을 출력한다.
const resultConsole = () => {
_number10Add(0)
.then((res) => _number20Add(res))
.then((res) => _number30Add(res))
.then((res) => _numberLog(res));
};
3) Promise의 요청 상태
💡 아래의 이미지는 Promise의 데이터 통신에 대한 흐름을 그려주고 있다.
최초 '대기 상태(Pending)'에서는 new Promise()를 통한 객체 생성을 나타내며, 해당 객체 내에서 통신을 하였을 때, 성공을 하게 되면 '이행 상태(fulfilled)'를 진행하고 실패를 하였을 경우 '거부 상태(Rejected)'를 수행한다. 해당 단계에 대해서는 아래에 상세히 공부해 봅니다.
[출처] Promise - MDN
1. 대기(Pending) 상태
💡 비동기 처리가 수행되기 이전의 상태를 의미하며 이행하지도 거부하지도 않은 상태를 의미한다.
const newPromise = () => {
return new Promise();
};
2. 이행(Fulfiled) 상태
💡 Promise를 통하여서 비동기 호출을 하였을 때, '성공’적으로 호출이 된 경우
기본 구조
new Promise (function (resolve, reject)){
resolve();
}
[적용 예시] 이행(Fulfiled) 상태 예시
useEffect(() => {
(async () => {
await numberAddPromise(100)
.then((response) => {
console.log('Success ::', response); // Success :: 101
})
.catch((error) => {
console.log('Error :: ', error);
});
})();
}, []);
const numberAddPromise = (number) => {
return new Promise((resolve) => {
resolve(number + 1);
});
// or
return Promise.resolve(number + 1);
};
이행 상태 예시에 대한 설명
- useEffect에서 numberAddPromise() 함수에 파라미터로 100을 전달하며 호출합니다.
- numberAddPromise()에서 이를 수행하게 되고, 연산한 값이 성공이 되었을 경우 resolve()로 반환을 해줍니다
- 반환된 값은. then((response)⇒)을 통하여 응답으로 전달이 됩니다.
- 최종 연산한 값이 101이라는 것을 확인합니다.
3. 거부(Rejected) 상태
💡 Promise를 통하여 비동기 호출을 하였으나 호출이 ‘실패’ 된 경우
기본 구조
new Promise(function(resolve, reject) {
reject();
});
[적용 예시] 거부(Rejected) 상태 예시
useEffect(() => {
(async () => {
await numberAddPromise(-1)
.then((response) => {
console.log('Success ::', response);
})
.catch((error) => {
console.log('Error :: ', error); // Error :: 마이너스 값입니다.
});
})();
}, []);
const numberAddPromise = (number) => {
return new Promise((resolve, reject) => {
if (number > 0) {
resolve(number + 1);
} else {
reject('마이너스 값입니다.');
}
});
// or
return Promise.resolve(number + 1);
};
거부 상태 예시에 대한 설명
- useEffect에서 numberAddPromise() 함수에 파라미터로 -1을 전달하며 호출합니다.
- numberAddPromise()에서 이를 수행하게 되고, 조건에 만족을 하지 못할 경우 reject()로 반환해 줍니다
- reject로 반환된 값은. catch((error)⇒)을 통하여 응답으로 전달이 됩니다.
- 최종 반환받은 메시지가 ‘마이너스 값입니다.'라고 결과가 출력됩니다.
오늘의 결론
동기와 비동기에 대해서 명확하게 공부하고 상황에 맞게 동기/비동기 데이터 통신을 수행하도록 하자.
그리고 Promise에 대한 이해는 명확하게 하고 개발을 하자.
오늘도 감사합니다😀
반응형
'Javascript & Typescript > 이해하기' 카테고리의 다른 글
[TS] 타입스크립트(Typescript) 이해하기-1 (정의, 동작원리, 특징) (0) | 2022.03.17 |
---|---|
[JS] Promise 이해하기 -2 (Promise 체이닝, Promise.all, async/await) (0) | 2022.03.13 |
[JS] 루프와 반복 함수 이해하기 (0) | 2022.01.26 |
[JS] ES5 / ES6(ECMAScript 2015) 이해하기 (0) | 2022.01.11 |
[JS] 변수(Variable) 이해하기 (0) | 2022.01.09 |