Promise
- 비동기 작업을 제어하기 위해 나온 개념
- callback hell에서 어느정도 벗어날 수 있게 도와줌
- Promise로 정의된 작업끼리는 연결이 가능하며 이를 사용해 코드의 depth가 크게 증가히지 않는 효과가 있음
기본 사용 방법
const promise = new Promise((resolve, reject) => {
})
function asyncPromiseWork() {
return new Promise((resolve, reject) => {
return resolve('completed');
})
}
asyncPromiseWork().then(result => console.log(result));
promise chaining
- 순차적으로 처리해야하는 비동기 작업이 여러 개 있을 경우 사용
- promise.then의 결과 값으로 promise가 반환되기 때문에 .then을 체인 형식으로 사용이 가능
new Promise((resolve, reject) => setTimeout(() => resolve(1), 100))
.then(result => {
console.log(result);
return result + 1;
}).then(result => {
console.log(result);
return result + 2;
}).then(result => {
console.log(result);
})
new Promise((resolve, reject) => setTimeout(() => resolve(1), 100))
.then(result => {
console.log(result);
return new Promise((resolve, reject) =>
setTimeout(() => resolve(result + 1), 100)
);
}).then(result => {
console.log(result);
return result + 2;
}).then(result => {
console.log(result);
})
promise chaining 오류 처리
fisrtPromiseWork()
.then(result => {
return secondPromiseWork(result);
}).then(result => {
return thirdPromiseWork(result);
}).then(result => {
return finalPromiseWork(result);
}).catch(e => {
console.log('오류 발생');
}).finally(() => {
console.log('작업 끝');
})
- catch를 넣지 않은 경우 promise chain 중 에러가 발생했을 때 chain이 멈춤 ⇒ catch를 사용하자!
- catch를 중간에 넣고 작업을 연결해도 동작함
callback함수를 promise 형태로 만들기
const delay = (delayTime) => new Promise((resolve) => {
setTimeout(resolve, delayTime);
})
delay(5000)
.then(() => {
return delay(3000);
}).then(() => {
console.log('complete');
})
promise 내장 함수
Promise.all(iterable)
- iterable에 주어진 모든 promise가 동시에 실행된 후 새로운 promise를 반환
- 여러 promise를 동시에 처리할 때 유용함
- 주어진 promise 중 하나라도 reject되는 경우 첫 번째로 reject된 promise를 이유로 자신도 거부함
Promise.all([
new Promise(resolve => setTimeout(resolve, 3000, 1)),
new Promise(resolve => setTimeout(resolve, 2000, 2)),
new Promise(resolve => setTimeout(resolve, 1000, 3))
]).then(result => console.log(result));
Promise.race(iterable)
- Promise.all과 비슷하지만 가장 먼저 처리되는 프로미스의 결과(성공, 실패)를 반환
- 많이 사용하진 않음
Promise.race([
new Promise(resolve => setTimeout(resolve, 3000, 1)),
new Promise(resolve => setTimeout(resolve, 2000, 2)),
new Promise(resolve => setTimeout(resolve, 1000, 3))
]).then(result => console.log(result));
Promise.any(iterable)
- Promise.all과 비슷하지만 가장 먼저 성공(resolve)한 promsie가 존재하면 종료
Promise.any([
new Promise(resolve => setTimeout(resolve, 3000, 1)),
new Promise(resolve => setTimeout(resolve, 2000, 2)),
new Promise(resolve => setTimeout(resolve, 1000, 3))
]).then(result => console.log(result));
Promise.allSettled()
- 주어진 모든 프로미스를 수행한 후 각 프로미스에 대한 결과를 나타내는 객체 배열을 반환
- 각 promise의 실행 결과를 알고 싶을 때 사용
Promise.allSettled([
new Promise(resolve => setTimeout(resolve, 3000, 1)),
new Promise(resolve => setTimeout(resolve, 2000, 2)),
new Promise(resolve => setTimeout(resolve, 1000, 3))
]).then(result => console.log(result));
Promise.resolve
- 주어진 값으로 이행하는 Promise.then 객체를 만듬
- 주어진 값이 promise인 경우 promise가 반환됨
- return type을 promise로 맞춰줄 때 종종 사용함
const promise1 = Promise.resolve(123);
promise1.then((value) => {
console.log(value);
});
async, await
- Promise가 callback depth를 1단계로 줄여주지만 아직 불편한 점이 있음
- .then() 체이닝을 통해 비동기 작업을 하므로 코드가 복잡함
- .catch()를 통해 오류를 처리하므로 오류 처리 로직이 분리되어 가독성이 떨어짐
⇒ async, await는 try, catch, finally를 사용!
- async, await를 사용하면 Promise를 비동기 작업이 수행되지만 동기 코드처럼 보이게 코드 작성이 가능
const delay = (delayTime) => new Promise((resolve) => {
setTimeout(resolve, delayTime);
})
const work = () => {
delay(100)
.then(() => {
console.log('work 1 complete');
return delay(100);
}).then(() => {
console.log('work 2 complete');
return delay(100);
}).then(() => {
console.log('work 3 complete');
return delay(100);
}).then(() => {
console.log('all complete');
})
}
work();
const work2 = async () => {
await delay(100);
console.log('work 1 complete');
await delay(100);
console.log('work 2 complete');
await delay(100);
console.log('work 3 complete');
await delay(100);
console.log('all complete');
}
work2();
async 함수 정의 방법
- async 키워드가 붙은 함수는 실행 결과를 Promise로 감싸게됨
async function asyncFunc () {
const res = await request(...);
}
const asyncFunc = async () {
const res = await request(...);
}
fetch api
- 비동기 https 요청을 좀 더 편하게 사용할 수 있는 API
- XMLHTTPRequest를 대체
- Promise 기반으로 동작 ⇒ promise chaining 응용 가능!
- fetch의 기본 응답 결과는 Response 객체!
- Response 객체를 얻은 뒤엔 응답을 json으로 바꾸거나 text로 바꾸는 등의 처리를 해줘야함
- fetch는 HTTP error가 발생해도 reject되지 않음(네트워크 에러나 요청이 완료되지 않은 경우만 reject 됨) ⇒ fetch가 성공했는지 확인하는 과정이 필요함(response의 status code나 ok를 확인)
사용 방법
fetch('https://dummyjson.com/products/1')
.then(res => res.json())
.then(json => console.log(json))
fetch('https://dummyjson.com/products/undefined')
.then(res => {
if (res.ok){
return res.json();
}
throw new Error('요청 중 오류 발생');
})
.then(json => console.log(json))
.catch(e => console.log(e.message));