지금까지 ajax로만 비동기처리를 했었는데, 찾아보니 Promise라는 객체를 이용해서 비동기 처리를 하는 경우가 많았다. fetch에 대해 정리해보고자 한다.
fetch
fetch는 Promise 기반의 API로, JavaScript에서 웹 리소스를 비동기적으로 가져오기 위한 방법을 제공한다.
fetch는 리소스의 경로(URL)를 최소 인자로 받는데,
fetch가 호출된 리소스에 대한 Promise를 반환하며, 반환된 Promise 객체는 요청이 성공적으로 완료되었을 때 HTTP 응답을 나타내는 Response 객체로 이행(resolved)된다.
fetch('https://example.com/data')
.then(response => response.json()) // 응답을 JSON으로 파싱
.then(data => console.log(data)) // 데이터 처리
.catch(error => console.error('Error:', error)); // 오류 처리
fetch는 두 번째 인자로 옵션 객체를 받는다. 요청 메소드, 헤더, 본문 등을 설정할 수 있다.
fetch('https://example.com/data', {
method: 'POST', // 요청 메소드
headers: {
'Content-Type': 'application/json', // 콘텐츠 타입 설정
},
body: JSON.stringify({
name: 'John Doe',
login: 'john.doe',
}), // 보낼 데이터
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));
async / await
promise객체와 fetch를 검색하다보면 async와 await도 많이 나오더라.
async와 await는 자바스크립트에서 비동기 작업을 더 쉽게 작성할 수 있게 해주는 문법이다.
async 함수는 항상 Promise객체를 반환하며, 함수 내부에서 await 키워드를 사용하여 프로미스의 결과를 기다린다.
1. async 함수 선언: 함수 앞에 async 키워드를 추가한다. 이 함수는 프로미스를 반환한다.
2. await 표현식 사용: async 함수 내에서 프로미스의 결과가 필요할 때, await 키워드를 사용하여 프로미스의 해결을 기다린다. await는 async 함수 내에서만 사용할 수 있다.
async와 await를 사용하여 응답을 기다린 후, JSON으로 변환하고 콘솔에 결과를 출력한다.
// async 함수 선언
async function fetchData(url) {
try {
// await를 사용하여 프로미스의 해결을 기다림
const response = await fetch(url);
// 응답 상태 확인
if (!response.ok) {
throw new Error(HTTP error! status: ${response.status});
}
// 응답 본문을 JSON으로 변환
const data = await response.json();
// 데이터 처리
console.log(data);
} catch (error) {
// 오류 처리
console.error("Could not fetch data: ", error);
}
}
// 함수 호출
fetchData('https://example.com/data');
만약 요청이 실패하거나 예외가 발생하면, catch 블록에서 이를 적절히 처리한다.
Promise?
Promise의 가장 큰 장점은 비동기 코드의 중첩(nesting)을 피할 수 있다는 점이다. 콜백 함수를 연속해서 사용하던 기존의 접근 방식(일명 콜백지옥이라고도 한다.)에서 벗어나 코드의 가독성을 높이고 유지 보수를 용이하게 한다.
비동기 작업이 처리되는 동안 Promise는 비동기 작업을 대기(pending), 이행(fulfilled), 거부(rejected)의 세 가지 상태로 관리한다.
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
어떻게 적용할까?
사용자 정보를 가져와서, 그 정보를 사용해 로그인, 로그인 성공 후 사용자의 프로필 정보를 가져오는 경우를 예시로 콜백함수를 promise 체이닝으로, 그리고 await으로 표현해봤다.
콜백지옥
getUser(userId, function(err, user) {
if (err) {
console.error('Error fetching user:', err);
} else {
loginUser(user, function(err, session) {
if (err) {
console.error('Login failed:', err);
} else {
getUserProfile(session, function(err, profile) {
if (err) {
console.error('Error fetching profile:', err);
} else {
console.log('Profile Data:', profile);
}
});
}
});
}
});
Promise 체이닝
// getUser, loginUser, getUserProfile이 Promise를 반환하도록 가정
function getUser(userId) {
return new Promise((resolve, reject) => {
// 비동기 작업 예시
fetch(`https://api.example.com/users/${userId}`)
.then(response => response.json())
.then(data => resolve(data))
.catch(err => reject(err));
});
}
function loginUser(user) {
return new Promise((resolve, reject) => {
// 사용자 로그인 처리 예시
fetch('https://api.example.com/login', {
method: 'POST',
body: JSON.stringify(user),
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(session => resolve(session))
.catch(err => reject(err));
});
}
function getUserProfile(session) {
return new Promise((resolve, reject) => {
// 프로필 정보 가져오기 예시
fetch(`https://api.example.com/profiles/${session.userId}`)
.then(response => response.json())
.then(profile => resolve(profile))
.catch(err => reject(err));
});
}
// 함수 사용
getUser('userId')
.then(user => loginUser(user))
.then(session => getUserProfile(session))
.then(profile => console.log('Profile Data:', profile))
.catch(error => console.error('Error:', error));
async, await
// getUser, loginUser, getUserProfile이 각각 Promise를 반환한다고 가정
async function getUser(userId) {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return await response.json();
}
async function loginUser(user) {
const response = await fetch('https://api.example.com/login', {
method: 'POST',
body: JSON.stringify(user),
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) {
throw new Error('Login failed');
}
return await response.json();
}
async function getUserProfile(session) {
const response = await fetch(`https://api.example.com/profiles/${session.userId}`);
if (!response.ok) {
throw new Error('Failed to fetch profile');
}
return await response.json();
}
async function displayUserProfile(userId) {
try {
const user = await getUser(userId);
const session = await loginUser(user);
const profile = await getUserProfile(session);
console.log('Profile Data:', profile);
} catch (error) {
console.error('Error:', error);
}
}
// 함수 실행
displayUserProfile('userId');
'프로그래밍 > Javascript' 카테고리의 다른 글
[모던 자바스크립트 Deep Dive] 브라우저 렌더링 과정 (0) | 2024.08.27 |
---|---|
[JS] 변수: var, let, const (0) | 2024.05.28 |
[Javascript] 함수 선언, 함수 표현, 객체의 메서드 (0) | 2024.04.17 |
[Javascript] Function() 생성자, 화살표 함수 (0) | 2024.04.17 |