[JS] 프로미스
21069 단어 JavaScriptJavaScript
비동기 함수
: 함수 내부에 비동기로 동작하는 코드를 포함한 함수
- 비동기 함수 호출 시, 함수 내부의 비동기 코드가 완료되지 않아도 즉시 종료
- 함수가 종료된 이후에 완료
- 함수 내부의 비동기 코드의 처리 결과를 외부로 반환 or 상위 스코프 변수에 할당할 경우, 기대한 대로 동작하지 않음
-> 비동기 함수의 처리 결과(서버의 응답 등)에 대한 후속 처리는 비동기 함수 내에서 수행해야 함- 비동기 함수에 비동기 처리 결과에 대한 후속처리를 수행하는 콜백 함수 전달하는 것이 일반적
콜백 함수
- 비동기 처리를 위한 하나의 패턴
콜백 패턴의 단점
1) 콜백 헬
- 비동기 처리 결과를 가지고 또다시 비동기 함수를 호출하는 경우
- 콜백 함수 호출이 중첩되어 복잡도가 높아지는 현상
- 가독성이 좋지 않음 -> 실수 유발의 원인
2) 에러 처리의 한계
가장 심각한 문제점- 비동기 함수의 콜백 함수를 호출하는 호출자가 비동기 함수가 아니므로
비동기 함수의 콜백 함수가 발생 시킨 에러를 잡지 못한다.
try {
setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch(e) {
// setTimeout의 콜백 함수에서 발생한 에러를 캐치하지 못한다.
console.error('캐치한 에러', e);
}
3) 여러 개의 비동기 처리를 한 번에 처리하는 데 한계
1. 프로미스
- ES6에서 비동기 처리를 위한 또 다른 패턴
- 표준 빌트인 객체 (호스트 객체 X)
- 비동기 처리 상태와 처리 결과를 관리하는 객체
-> 전통적인 콜백 패턴이 가진 단점 보완, 비동기 처리 시점 명확하게 표현 가능
2. 프로미스 생성
- Promise 생성자 함수 + new 연산자 => 프로미스(Promise 객체) 생성
- 인수: 비동기 처리를 수행할 콜백 함수
- resolve: 비동기 처리 성공 시 호출되는 함수
- reject: 비동기 처리 실패 시 호출되는 함수
const promise = new Promise((resolve, reject) => {
if(/* 비동기 처리 성공 */) {
resolve('result');
} else { /* 비동기 처리 실패 */
reject('failure reason');
}
});
- 프로미스의 상태 정보
- pending: 비동기 처리 수행 전 = 프로미스 생성 직후
- settled: pending이 아닌 상태 = 비동기 처리가 수행된 상태- 한 번 settled 상태가 되면 다른 상태로 변화할 수 X
- fulfilled: 비동기 처리 수행(성공) = resolve 함수 호출 시
- rejected: 비동기 처리 수행(실패) = reject 함수 호출 시
- 한 번 settled 상태가 되면 다른 상태로 변화할 수 X
3. 프로미스의 후속 처리 메서드
- 프로미스의 비동기 처리 상태 변화에 따른 후속 처리
- 후속 처리 메서드에 인수로 전달한 콜백 함수가 선택적으로 호출됨
- 항상 프로미스를 반환하며 비동기로 동작
- 콜백 함수가 프로미스가 아닌 값을 반환하면, 암묵적으로 resolve or reject하여 프로미스를 생성해 반환
1) Promise.prototype.then
- 첫 번째 콜백 함수: fulfilled 상태가 되면(resolve 함수가 호출되면) 호출
- 두 번째 콜백 함수: rejected 상태가 되면(reject 함수가 호출되면) 호출
new Promise(resolve => resolve('fulfilled'))
.then(v => console.log(v), e => console.log(e)); // fultilled
2) Promise.prototype.catch
- rejected 상태인 경우에만 호출
then(undefined, onRejected)
와 동일하게 동작
new Promise((_, reject) => reject(new Error('rejected')))
.catch(e => console.log(e)); // Error: rejected
3) Promise.prototype.finally
- 프로미스의 성공(fulfilled) / 실패(rejected) 와 상관없이 무조건 한 번 호출
- 공통적으로 수행해야 할 처리 내용이 있을 때 유용
4. 프로미스의 에러 처리
- 프로미스의 후속 처리 메서드
then
의 두 번째 콜백 함수 orcatch
로 에러 처리 가능
-catch
메서드에서 하는 것이 가독성이 좋고 명확함
5. 프로미스 체이닝
- 후속 처리 메서드는 언제나 프로미스를 반환하므로 연속적으로 호출 가능
- 비동기 처리 결과를 전달받아 후속 처리를 하므로 콜백 헬 발생 X
-> 프로미스도 콜백 패턴을 사용하므로 가독성이 좋진 않음
=> ES8에서 도입된 async/await 사용하여 해결- 후속 처리 메서드 없이 (동기 처리처럼)프로미스가 처리 결과를 반환하도록 구현 가능
const url = 'https://...';
// 프로미스 체이닝 이용
promiseGet(`${url}/posts/1`)
.then(({ userId }) => promiseGet(`${url}/users/${userId}`))
.then(userInfo => console.log(userInfo))
.catch(err => console.log(err));
// async/await 이용
(async () => {
const { userId } = await promiseGet(`${url}/posts/1`);
const userInfo = await promiseGet(`${url}/users/${userId}`);
console.log(userInfo);
})();
6. 프로미스의 정적 메서드
1) Promise.resolve / Promise.reject
- 이미 존재하는 값을 래핑하여 프로미스를 생성하기 위해 사용
const resolvedPromise = Promise.resolve([1, 2, 3]);
resolvedPromise.then(console.log); // [1, 2, 3]
// 위 예제와 동일하게 동작
const resolvedPromise = new Promise(resolve => resolve([1, 2, 3]));
resolvedPromise.then(console.log); // [1, 2, 3]
2) Promise.all
- 여러 개의 비동기 처리를 모두 병렬 처리할 때 사용
- 이터러블을 인수로 전달 받음
- 모든 프로미스가 fulfilled 상태가 되면 모든 처리 결과를 배열에 저장해 새로운 프로미스 반환
- 처리 순서 보장
- 프로미스 하나라도 reject 상태가 되면 즉시 종료
const requestData1 = () => new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () => new Promise(resolve => setTimeout(() => resolve(3), 1000));
Promise.all([requestData1(), requestData2(), requestData3()])
.then(console.log) // [1, 2, 3]
.catch(console.error);
3) Promise.race
- 이터러블을 인수로 전달 받음
Promise.all
과 비슷하나 가장 먼저 fulfilled 상태가 된 프로미스의 처리 결과를 새로운 프로미스를 통해 반환
4) Promise.allSettled
- 이터러블을 인수로 전달 받음
- 모든 프로미스가 settled 상태(fulfilled or rejected)가 되면 처리 결과를 배열로 반환
7. 마이크로태스크 큐
- 프로미스의 후속 처리 메서드(then, catch, finally)의 콜백함수가 저장되는 곳
- 비동기 함수의 콜백 함수 or 이벤트 핸들러는 태스크 큐에 일시 저장
- 우선 순위: 마이크로태스크 큐 > 태스크 큐
- 마이크로태스크 큐가 비면 태스크 큐에서 대기하고 있는 함수를 실행시킴
8. fetch
XMLHttpRequest
객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API- 사용법이 간단하고 프로미스를 지원
- HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환
Author And Source
이 문제에 관하여([JS] 프로미스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hahaha/JS-프로미스저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)