Promise
2025. 3. 30. 22:44ㆍWeb Development/JavaScript
Promise
ES6에서 도입된 Promise는 비동기 작업의 최종 완료(또는 실패) 및 결과 값을 나타내는 객체입니다. 콜백 지옥 문제를 해결하고 더 나은 오류 처리를 제공합니다.
Promise 기본 개념
Promise는 다음 중 하나의 상태를 가집니다:
- 대기(pending): 초기 상태, 이행되거나 거부되지 않음
- 이행(fulfilled): 작업이 성공적으로 완료됨
- 거부(rejected): 작업이 실패함
// Promise 생성
const myPromise = new Promise((resolve, reject) => {
// 비동기 작업 수행
const success = true;
if (success) {
resolve("작업 성공!"); // 이행 상태로 전환
} else {
reject(new Error("작업 실패!")); // 거부 상태로 전환
}
});
// Promise 사용
myPromise
.then(result => {
console.log("성공:", result); // "성공: 작업 성공!"
})
.catch(error => {
console.error("오류:", error);
});
Promise 메서드
.then(), .catch(), .finally()
function fetchUser(userId) {
return new Promise((resolve, reject) => {
// 비동기 작업 (예: API 호출)
setTimeout(() => {
if (userId > 0) {
resolve({ id: userId, name: `사용자${userId}` });
} else {
reject(new Error("유효하지 않은 사용자 ID"));
}
}, 1000);
});
}
fetchUser(123)
.then(user => {
console.log("사용자 정보:", user);
return user.id; // 다음 then으로 값 전달
})
.then(userId => {
console.log("사용자 ID:", userId);
throw new Error("의도적인 오류"); // 오류 발생
})
.catch(error => {
console.error("처리 중 오류 발생:", error);
return "오류 복구"; // catch 후에도 체인 계속
})
.then(value => {
console.log("catch 이후 값:", value);
})
.finally(() => {
console.log("성공 또는 실패 여부와 관계없이 항상 실행");
});
Promise.all(), Promise.race(), Promise.allSettled()
// 여러 Promise 동시 처리
const promise1 = Promise.resolve("첫 번째 결과");
const promise2 = new Promise(resolve => setTimeout(() => resolve("두 번째 결과"), 1000));
const promise3 = fetch('https://api.example.com/data').then(res => res.json());
// Promise.all - 모든 Promise가 이행될 때까지 기다림 (하나라도 거부되면 즉시 거부됨)
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log("모든 결과:", results); // [첫 번째 결과, 두 번째 결과, API 응답 데이터]
})
.catch(error => {
console.error("하나 이상의 Promise가 거부됨:", error);
});
// Promise.race - 가장 먼저 완료(이행 또는 거부)되는 Promise 결과를 반환
Promise.race([promise1, promise2, promise3])
.then(result => {
console.log("가장 빠른 결과:", result); // 첫 번째 결과 (이미 이행된 상태)
})
.catch(error => {
console.error("가장 빠르게 거부된 Promise:", error);
});
// Promise.allSettled - 모든 Promise가 완료될 때까지 기다린 후 각각의 상태와 결과 반환
Promise.allSettled([promise1, promise2, promise3])
.then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Promise ${index + 1} 이행:`, result.value);
} else {
console.log(`Promise ${index + 1} 거부:`, result.reason);
}
});
});
콜백을 Promise로 변환
레거시 API나 콜백 기반 함수를 Promise로 변환하여 사용할 수 있습니다.
// 콜백 기반 함수를 Promise로 변환
function readFilePromise(filepath) {
return new Promise((resolve, reject) => {
fs.readFile(filepath, 'utf8', (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
// 사용 예
readFilePromise('example.txt')
.then(data => {
console.log('파일 내용:', data);
})
.catch(err => {
console.error('파일 읽기 오류:', err);
});
// 타이머를 Promise로 변환
function delay(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
// 사용 예
delay(2000)
.then(() => {
console.log('2초 지남');
return delay(1000);
})
.then(() => {
console.log('추가 1초 지남');
});
Promise 체이닝으로 콜백 지옥 해결
Promise를 사용하면 중첩된 콜백 대신 체인 형태로 코드를 작성할 수 있습니다.
// 콜백 지옥을 Promise 체인으로 변환
function fetchData(url) {
return fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP 오류! 상태: ${response.status}`);
}
return response.json();
});
}
fetchData('https://api.example.com/users')
.then(users => {
console.log('사용자 목록:', users);
return fetchData(`https://api.example.com/users/${users[0].id}/posts`);
})
.then(posts => {
console.log('첫 번째 사용자의 포스트:', posts);
return fetchData(`https://api.example.com/posts/${posts[0].id}/comments`);
})
.then(comments => {
console.log('첫 번째 포스트의 댓글:', comments);
})
.catch(error => {
console.error('에러 발생:', error);
});
'Web Development > JavaScript' 카테고리의 다른 글
실전 비동기 프로그래밍 패턴 (0) | 2025.03.30 |
---|---|
async/await (0) | 2025.03.30 |
콜백 함수 (0) | 2025.03.30 |
비동기 프로그래밍 (0) | 2025.03.30 |
실전 DOM 조작 예제 (0) | 2025.03.30 |