일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Component
- 브라우저
- 원티드
- 프론트엔드
- v9
- Frontend
- TypeScript
- 알고리즘
- firebase
- react localStorage
- JavaScript
- array
- JS
- 자바스크립트
- 리액트
- state
- Redux
- 프리온보딩
- CORS
- localstorage
- 프로그래머스
- react
- 파이어베이스
- 타입스크립트
- es6
- 비트 연산자
- 컴포넌트
- til
- axios
- Reducer
- Today
- Total
도리쓰에러쓰
[JavaScript] 자바스크립트에서의 Promise 본문
자바스크립트의 Promise를 알아보기 전에 동기와 비동기의 차이에 대해 알아보자.
1. 동기(Synchronous)와 비동기(Asynchronous)
1️⃣ 동기(Synchronous)
- 1번부터 4번까지의 명령이 있을 때 순차적으로 명령이 진행
- 앞의 명령이 끝날 때까지 뒤의 명령은 먼저 실행되지 않는다.
2️⃣ 비동기(Asynchronous)
- 명령의 순서와 상관없이 동시에 명령 실행
2. Promise
자바스크립트는 비동기 처리를 위해 콜백 함수를 사용한다.
하지만 콜백 중첩, 즉 콜벡 헬로 인해 코드의 가독성이 떨어지고,
비동기 처리 중 발생한 에러의 처리가 곤란한 등의 문제가 발생할 수 있다.
async(1, () => {
async(2, () => {
async(3, () => {
async(4, () => {
async(5, () => {
console.log('콜백의 늪');
});
});
});
});
});
Promise는 비동기 연산이 종료된 이후에 결과 값과 실패 사유를 처리하기 위한 것이고,
이것을 이용하면 비동기 메서드를 마치 동기 메서드처럼 값을 반환할 수 있다.
Promise는 다음 중 하나의 상태를 가진다.
1️⃣ 대기(Pending): 이행하지도, 거부하지도 않은 초기 상태
2️⃣ 이행(Fulfilled): 연산이 성공적으로 완료
3️⃣ 거부(Rejected): 연산 실패
아래 예제를 보자.
const exFunc = (param) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (param) resolve('성공');
else reject(new Error('실패'));
}, 3000);
});
};
위 예제는 Promise 객체를 리턴하는 예제이다.
Promise는 resolve와 reject를 파라메터로 받고 있는데,
일단 new Promise로 Promise가 생성되는 직후부터 resolve나 reject가 호출되기 전까지의 순간을 대기(Pending) 상태라고 볼 수 있다.
이 후 비동기 작업이 성공하면 resolve 함수를 호출하고 실패하면 reject 함수를 호출한다.
💡 then()
then() 메서드는 Promise를 리턴하고 두개의 콜백 함수를 인수로 받는다.
하나는 Promise가 이행했을 때, 다른 하나는 거부했을 때를 위한 콜백 함수이다.
p.then((value) => {
// 이행
}, (reason) => {
// 거부
});
💡 catch()
catch() 메서드는 거부했을 때 즉, reject인 경우에만 실행된다.
p.then((value) => {
// 이행
}.catch((reason) => {
// 거부
});
then() 메서드로 이행과 거부 상태가 발생했을 때의 처리를 해줄 순 있지만,
코드의 가독성을 위해 then() 메서드는 이행했을 때
catch() 메서드는 거부했을 때의 코드를 작성하는 것이 좋다.
💡 finally()
finally() 메서드는 이행과 거부 상관 없이 처리가 완료되면 실행된다.
p.then((value) => {
// 이행
}.catch((reason) => {
// 거부
}.finally(() => {
console.log('성공');
});
💡 Promise.all()
- 사용법: Promise.all(iterable);
📌 iterable: array처럼 순회 가능한 객체
Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후 혹은
프로미스가 주어지지 않았을 때 이행하는 Promise를 반환한다.
아래 예제를 확인해보자.
const p1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('첫번째'), 1000);
});
};
const p2 = (msg) => {
console.log(msg);
return new Promise((resolve, reject) => {
setTimeout(() => resolve('두번째'), 3000);
});
};
const p3 = (msg) => {
console.log(msg);
return new Promise((resolve, reject) => {
setTimeout(() => resolve('세번째'), 2000);
});
};
Promise.all([p1, p2, p3])
.then(values => {
console.log(values);
})
.catch(error => {
console.log(error);
});
// 출력: ['첫번째', '두번째', '세번째']
위 예제는 p1, p2, p3 프로미스가 모든 프로미스가 이행되고
그 작업이 완료하여 then() 메소드를 통해 배열로 리턴한 예제이다.
3개 모두 문제 없이 이행되었기 때문에 배열로 리턴하였지만, 만약 하나라도 실패한 것이 있다면 어떻게 될까?
아래 예제를 보자.
const p1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('첫번째'), 1000);
});
};
const p2 = (msg) => {
console.log(msg);
return new Promise((resolve, reject) => {
setTimeout(() => resolve('두번째'), 3000);
});
};
const p3 = (msg) => {
console.log(msg);
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('거부')), 2000);
});
};
Promise.all([p1, p2, p3])
.then(values => {
console.log(values);
})
.catch(error => {
console.log(error.message);
});
// 출력: '거부'
위 예제처럼 어느 하나라도 실패했다고 뜨면 어떤 데이터도 얻지 못한다.
그래서 Promise.all()을 사용할 때는 다 보여주거나 혹은 모든 정보를 다 보여주지 않거나 할 때 사용하는 것이 좋다.
💡 Promise.race()
Promise.race()는 Promise.all()과 사용법이 같다.
Promise 객체를 반환하며 iterable 안에 있는 프로미스 중 가장 먼저 완료된 것의 결과값을 그대로 이행하거나 거부한다.
const p1 = () => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 500, '첫번째');
});
};
const p2 = (msg) => {
console.log(msg);
return new Promise((resolve, reject) => {
setTimeout(resolve, 100, '두번째');
});
};
Promise.race([p1, p2])
.then(value => {
console.log(value);
});
// 출력: '두번째'
위 예제는 p1, p2 중 p2가 먼저 완료되어 '두번째'가 출력된 예제이다.
'두번째'가 출력되고 '첫번째'가 reject를 예상하고 있었는데 이미 가장 먼저 완료된 p2가 있어서 무시된 것이다.
💡 Promise.allSettled()
Promise.allSettled()도 마찬가지로 Promise.all()과 사용법이 같다.
Promise.all() 메서드와 반대로 하나가 실패하더라도 모든 Promise의 결과를 받을 수 있다.
const p1 = Promise.resolve('첫번째');
const p2 = new Promise((resolve, reject) => setTimeout(reject, 100, '두번째'));
const p3 = Promise.resolve('세번째');
Promise.allSettled([p1, p2, p3])
.then(results => {
results.forEach((result) => console.log(result.value));
})
.catch(error => {
console.log(error.message);
});
// 출력
// '첫번째'
// undefined
// '세번째'
에러가 난 p2만 undefined라고 출력되고 p1과 p3는 정상적으로 콘솔에 출력된 것을 확인할 수 있다.
'JavaScript > JS' 카테고리의 다른 글
[JavaScript] 자바스크립트는 비동기적인데 왜 싱글 스레드일까? (0) | 2022.08.16 |
---|---|
[JavaScript] 자바스크립트에서의 비동기 처리 async - await (0) | 2022.08.16 |
[JavaScript] 실행 컨텍스트(Execution Context)란? (0) | 2022.08.10 |
[JavaScript] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) (0) | 2022.08.08 |
[JavaScript] this란? (0) | 2022.08.05 |