오늘은 그렇다 나왔다 프로미스다..
프로미스(Promise)는 JavaScript에서 비동기 연산을 더 편리하게 관리할 수 있도록 하는 객체입니다.
Promise는 비동기 연산의 최종 완료(또는 실패) 및 그 결과 값을 나타냅니다.
Promise는 주로 서버에서 데이터를 가져오는 등의 비동기 작업에 사용됩니다.
프로미스는 3가지 상태를 가집니다:
- pending: 초기 상태로, 이행되거나 거부되지 않음.
- fulfilled: 연산이 성공적으로 완료됨.
- rejected: 연산이 실패함.
프로미스는 이러한 상태를 갖고, pending에서 fulfilled 또는 rejected 상태로 변경될 수 있습니다.
한번 상태가 변경되면, 그 상태는 영구적이며 다시는 변경되지 않습니다.
다음은 프로미스의 생성과 사용 예제입니다:
let promise = new Promise((성공, 실패) => {
let condition = true;
// 이 조건은 실제로는 비동기 연산의 결과에 따라 결정됩니다.
// 그러니까 여기엔 복잡한 연산이나 서버에서 뭘 받아오는 등 시간 걸리는 것들이 들어간다..
if(condition) {
성공('Promise is fulfilled!');
} else {
실패('Promise is rejected!');
}
});
promise
.then((리졸브내용) => {
console.log(리졸브내용); // 'Promise is fulfilled!'
}).catch((리젝트내용) => {
console.log(리젝트내용); // 'Promise is rejected!'
});
// 그렇다 간단해 보인다..
위의 코드에서 new Promise를 통해 프로미스를 생성하고 있습니다.
resolve와 reject는 함수로, 비동기 작업이 성공적으로 완료되면 resolve를 호출하고, 그렇지 않으면 reject를 호출합니다.
그리고 then 메소드는 프로미스가 이행(fulfilled) 상태일 때 호출될 콜백 함수를 등록하며, catch 메소드는 프로미스가 거부(rejected) 상태일 때 호출될 콜백 함수를 등록합니다.
프로미스는 비동기 작업을 좀 더 편리하게 관리하도록 도와주며, 특히 복잡한 비동기 로직을 다룰 때 콜백 함수만을 사용하는 것보다 가독성과 관리 측면에서 유리합니다.
// 성공, 실패시 반환 값을 넘기고 싶다면?
// 무슨 힘든 연산 같은 걸 할 때는 이런식으로
let promise = new Promise((성공, 실패) => {
let 힘든거 = 1 + 2;
if(힘든거 == 3) {
성공(힘든거);
} else {
실패('너는 실패했다');
}
});
promise
.then((결과) => {
console.log(결과); // 3
}).catch((실패) => {
console.log(실패); // '너는 실패했다'
});
// ajax 같은 서버 통신 할 때는 이런식으로
let url = 'https://api.example.com/data'; // 대상 URL
let promise = new Promise((resolve, reject) => {
fetch(url)
.then(response => {
if(response.ok) {
return response.json();
} else {
throw new Error('Network response was not ok');
}
})
.then(data => resolve(data))
.catch(error => reject(error));
});
promise
.then(data => {
console.log(data); // 성공적으로 데이터를 받아왔을 때의 처리
}).catch(error => {
console.log('There has been a problem with your fetch operation: ', error.message); // 데이터를 받아오는 데 실패했을 때의 처리
});
이 코드는 fetch()를 통해 비동기적으로 데이터를 요청하고, 요청이 성공하면 받아온 데이터를 JSON 형식으로 파싱합니다.
그리고 파싱된 데이터는 resolve(data)를 통해 프로미스에 전달되고, 이후에 then 메소드를 통해 이 데이터를 받아서 처리할 수 있습니다.
만약 네트워크 요청이나 데이터 파싱 과정에서 문제가 생기면 reject(error)를 통해 에러를 프로미스에 전달하고, catch 메소드를 통해 이 에러를 처리할 수 있습니다.
// 헷갈리지 말것 :
// 1. 프로미스 문법이 막 뭘 비동기로 만들어주는 것은 아니다.
// 2. 자바스크립트 자체가 비동기 언어가 아니기 때문이다.
// 3. 그래서 '비동기' 적으로 동작하는 애들이 몇 개 있는 건데,
// setTimeout, 몇 시간뒤에 뭐뭐를 실행하라고 했으니까, 그 뭐뭐는 비동기 처럼 되는 것임.. 그냥 대기하는 것임.
// addEventListener, 클릭 같은거 하면 뭐뭐를 실행하라고 했으니까, 역시 그 뭐뭐가 비동기처럼.. 대기
// fetch, 이것도 서버 통신 하는 동안 결국은 대기해야 하는것임
// $.ajax, 얘는 Jquery 니까 패스 암튼 대기하겠지 뭐
// 관련하여 다음과 같이 물어봤다.
// 그런데 fetch 함수 같은건 완전히 비동기 처리가 되는 겁니까? 그러니까 만일 fetch 로 get 을 보냈는데, 받아오는 시간이 오래 걸린다면 브라우저가 멈추는 건 아닌 건가요? setTimeout 같은건 그냥 단순히 얼마 시간 뒤에 실행해 주세요 라는 뜻이고 만일 setTimeout의 콜백함수로 오래 걸리는 연산 같은게 들어있다면 그동안 멈추는 것 아닙니까?
맞습니다. JavaScript는 싱글 스레드(single-threaded) 언어입니다. 즉, 한 번에 하나의 작업만 처리할 수 있습니다. 하지만 비동기 처리를 통해, 일부 코드의 실행을 다른 작업이 끝날 때까지 "대기"시킬 수 있습니다. 이렇게 하면 일부 작업이 완료되기를 기다리는 동안 다른 코드를 실행할 수 있습니다. 이런 방식을 사용하면, 긴 시간이 걸리는 작업(예: 네트워크 요청, 파일 읽기 등)을 처리하는 동안 프로그램이 "멈추는" 것을 피할 수 있습니다.
fetch() 함수는 비동기적으로 동작합니다. 이 함수를 호출하면, 네트워크 요청이 시작되고 즉시 Promise 객체가 반환됩니다. 이 Promise 객체는 네트워크 요청의 완료를 나타냅니다. 네트워크 요청이 완료되면, 이 Promise 객체는 "이행" 상태가 되고, 요청의 결과(성공 또는 실패)를 나타내는 값으로 설정됩니다.
setTimeout() 함수도 비슷한 방식으로 동작합니다. 이 함수를 호출하면, 일정 시간이 경과한 후에 콜백 함수를 실행하도록 예약합니다. 그러나 이 함수의 콜백에 오래 걸리는 연산이 포함되어 있다면, 그 연산이 완료될 때까지 다른 JavaScript 코드의 실행이 막힐 수 있습니다. 이는 JavaScript가 싱글 스레드로 동작하기 때문입니다. 이런 경우를 피하려면, 오래 걸리는 연산을 비동기적으로 처리해야 합니다. 예를 들어, Web Worker를 사용하거나, 오래 걸리는 연산을 여러 작은 조각으로 나눠서 처리하는 방법이 있습니다.
// 그러면 fetch 함수가 호출되어 즉시 promise 객체를 반환하고 요청 결과를 기다리는 동안, 다른 코드들은 실행될 수 있는건가요?
네, 맞습니다. fetch() 함수를 호출하면 즉시 Promise 객체가 반환되고, 이 Promise 객체는 네트워크 요청이 완료될 때까지 이행 또는 거부 상태로 바뀌지 않습니다. 이 시간 동안, JavaScript 엔진은 fetch() 함수 이후의 코드를 계속 실행할 수 있습니다.
이것이 비동기 프로그래밍의 핵심 원칙 중 하나입니다. 즉, 시간이 오래 걸리는 작업을 수행하는 동안에도, 프로그램이 차단되지 않고 다른 작업을 계속 처리할 수 있어야 합니다.
이것은 프로미스를 사용하는 주요 이유 중 하나입니다. 프로미스는 시간이 오래 걸리는 작업의 결과를 나타내는 "프록시"로 작동하며, 그 결과가 준비될 때까지 다른 코드를 실행할 수 있게 해줍니다. 이 작업이 완료되면, 프로미스는 그 결과를 가지고 이행 상태가 되거나, 오류가 발생하면 거부 상태가 됩니다. 이행 또는 거부 상태가 된 프로미스는 .then() 또는 .catch() 메소드를 통해 처리할 수 있습니다.
// 그렇다고 합니다.. 비동기 함수 이후의 코드를 이어서 '계속' 실행할 수 있는 것 뿐 오래걸리는 건 오래걸린다
'javascript' 카테고리의 다른 글
[자바스크립트 28] 프로토타입과 상속 1 (0) | 2023.06.14 |
---|---|
[자바스크립트 27] 비동기 3(async/await) (1) | 2023.05.13 |
[자바스크립트 25] 비동기 1(콜백함수) (0) | 2023.05.13 |
[자바스크립트 24] DOM 조작 3(이벤트핸들러) (0) | 2023.05.13 |
[자바스크립트 23] DOM 조작 2(추가, 수정, 삭제) (0) | 2023.05.13 |