fetch() 함수 예시
- fetch()를 감싸는 외부 함수에 async를 붙인다.
- async가 붙으면 함수는 promise를 return
- fetch() 함수 앞에 await을 붙이면 fetch()의 promise 결과를 기다리며 함수는 일시 정지
- response.json() 앞에 await을 붙여서 json 파싱하는 동안 일시 정지
- 순차적으로 한 줄씩 진행되므로 동기 코드와 비슷한 형태가 되었다.
- await은 async함수 내에서만 사용 가능
- 오류 처리 : try-catch 구문 사용
async function 외부함수() {
try {
const response = await fetch('https://example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('An error occurred:', error);
}
}
async-await은 비동기 처리를 위한 패턴이다. Callback과 Promise의 단점을 보완하고 가독성 좋게 코드를 작성할 수 있다.
Callback의 단점
콜백 지옥 : 콜백 중첩 시 발생한다.
에러 처리의 어려움 : 에러 처리 로직을 따로 구현해야 하는 번거로움이 있다.
Promise의 단점
에러를 놓치는 경우 : then() 체인을 연결하다가 마지막에 catch() 메서드를 누락하는 경우
복잡한 비동기 제어 : 여러 비동기 작업을 순차적으로 실행한 다음 그 결과를 모아서 처리해야하는 경우
복잡한 비동기 제어의 경우를 예시로 promise와 async-await 비교
function fetchData() {
return fetch('https://example.com/data').then((response) => response.json());
}
function fetchMoreData(dataId) {
return fetch(`https://example.com/more-data/${dataId}`).then((response) => response.json());
}
// 여러 비동기 작업을 순차적으로 실행
fetchData()
.then((data) => {
console.log(data);
// 첫 번째 비동기 작업의 결과를 사용하여 두 번째 비동기 작업을 실행
return fetchMoreData(data.id);
})
.then((moreData) => {
console.log(moreData);
// 추가 로직...
})
.catch((error) => {
console.error('An error occurred:', error);
});
async
함수의 앞에 붙여서 사용한다.
해당 함수는 promise를 return한다.
await
async 내부에서만 사용 가능하다.
await이 붙은 비동기 함수가 완료되기까지 실행이 일시 중지된다.
async function fetchData() {
const response = await fetch('https://example.com/data');
return response.json();
}
async function fetchMoreData(dataId) {
const response = await fetch(`https://example.com/more-data/${dataId}`);
return response.json();
}
async function executeAsyncTasks() {
try {
const data = await fetchData();
console.log(data);
// 첫 번째 비동기 작업의 결과를 사용하여 두 번째 비동기 작업을 실행
const moreData = await fetchMoreData(data.id);
console.log(moreData);
// 추가 로직...
} catch (error) {
console.error('An error occurred:', error);
}
}
executeAsyncTasks();
동기 코드처럼 비동기 함수를 실행하고 기다렸다가 promise를 할당하여 사용한다.
callback
function fetchData(callback) {
// 데이터를 가져오는 시뮬레이션
const error = null; // 에러가 없다고 가정
const data = "Some data"; // 가져올 데이터
if (error) {
callback(error, null); // 에러가 있다면, 첫 번째 매개변수로 에러 전달
} else {
callback(null, data); // 에러가 없다면, 첫 번째 매개변수로 null, 두 번째 매개변수로 데이터 전달
}
}
// fetchData 함수 사용
fetchData((error, data) => {
if (error) {
console.error("An error occurred:", error); // 에러 처리
} else {
console.log("Received data:", data); // 정상적으로 데이터를 받아 처리
}
});
promise
위의 예제 중
catch (error) {
console.error('An error occurred:', error);
}
then() 메서드가 연속된 체인의 경우는 마지막에서 catch()를 작성하여 감지한다.
then() 메서드가 독립적으로 사용되는 경우 각각 catch() 작성해서 에러를 처리해야 한다.
이 두 가지 방식이 헷갈려서 실수가 발생할 가능성이 있다.
async-await
위의 예제 중
async function executeAsyncTasks() {
try {
const data = await fetchData();
console.log(data);
// 첫 번째 비동기 작업의 결과를 사용하여 두 번째 비동기 작업을 실행
const moreData = await fetchMoreData(data.id);
console.log(moreData);
// 추가 로직...
} catch (error) {
console.error('An error occurred:', error);
}
}
try 안에 로직을 작성하고 try 뒤에 catch를 통해 에러를 try 안에서 발생한 에러를 통합적으로 잡을 수 있다.