◼ Promise 객체
비동기 작업을 처리하고 관리하기 위해 사용한다.
new Promise로 새 poromis객체를 생성할 수 있고, fetch함수에도 사용한다.
가독성을 높여 콜백 헬(callback hell)이라는 문제를 해결하기 위해 promise를 많이 사용한다
promise에서 사용되는 함수, 메소드가 몇가지 적어보았다
비동기 실행 함수
- setTimeout
- setInterval
- addEventListener
promise 메소드
- then(): Promise가 이행됐을 때, 거부됐을 때, 또는 상태가 변할 때 호출할 콜백 함수를 등록합니다.
- catch(): Promise가 거부됐을 때 호출할 콜백 함수를 등록합니다. then() 메서드에서 발생한 에러를 처리하는 데 사용됩니다.
- finally(): Promise가 이행되거나 거부됐을 때 호출할 콜백 함수를 등록합니다. 무조건 실행되는 로직을 정의할 때 사용됩니다.
- resolve(): Promise를 이행시키는 함수입니다. 주어진 값을 포함하는 이행된 Promise를 반환합니다.
- reject(): Promise를 거부시키는 함수입니다. 주어진 이유로 거부된 Promise를 반환합니다.
- all(): 여러 개의 Promise를 동시에 실행하고, 모든 Promise가 이행될 때까지 기다린 후 이행된 값을 배열로 반환합니다. 하나라도 거부되면 첫 번째로 거부된 Promise를 반환합니다.
- race(): 여러 개의 Promise 중 가장 먼저 이행되거나 거부된 Promise를 반환합니다.
- allSettled(): 모든 Promise가 이행되거나 거부될 때까지 기다린 후 모든 Promise의 결과를 담은 배열을 반환합니다. Promise가 이행됐을 때는 { status: 'fulfilled', value: 이행된 값 } 형태의 객체를, 거부됐을 때는 { status: 'rejected', reason: 거부된 이유 } 형태의 객체를 포함합니다.
Response 객체
- text(): text 메소드는, fulfilled 상태이면서 리스폰스의 바디에 있는 내용을 string 타입으로 변환한 값을 '작업 성공 결과'로 가진 Promise 객체를 리턴
- json(): fulfilled 상태이면서, 리스폰스의 바디에 있는 JSON 데이터를 자바스크립트 객체로 Deserialize(역직렬화)해서 생겨난 객체를 '작업 성공 결과'로 가진 Promise 객체를 리턴
◼ Promisify
전통적인 형식의 비동기 실행 함수를 Promise 객체로 감싸서 그 Promise 객체를 리턴하는 형식으로 만드는 작업을 Promisify라고 한다.
function wait(text, milliseconds) { // 리턴
const p = new Promise((resolve, reject) => {
setTimeout(() => { resolve(text); }, 2000);
});
return p;
}
fetch('https://json.aaa.typicode.com/users') // promise 객체
.then((response) => response.text())
.then((result) => wait(`${result} END`, 2000)) // 2초 후에 리스폰스의 내용 뒤에 'END' 추가하고 리턴
.then((result) => { console.log(result); });
주의
콜백을 한 번만 실행하는 것들(setTimeout, readFile 등)만 Promisify해서 사용해도 되지만,콜백을 여러 번 실행하는 함수들(setInterval, addEventListener)등은 사용하면 안 된다
Promise 객체는 한번 pending 상태에서 fulfilled 또는 rejected 상태가 되고 나면, 첫 상태와 결과에 고정되어 바뀌지 않기 때문입니다.
◼ Promise chaining
Promise chaining을 사용하면 여러 개의 비동기 작업을 순차적으로 실행하고, 각 단계에서의 결과를 이용하여 다음 단계로 넘길 수 있다.
fetch('https://json.site.com/users') // 첫 번째 Promise
.then(response => response.json()) // 두 번째 Promise
.then(data => {
console.log(data); // 세 번째 Promise
return fetch('https://json.site.com/posts'); // 네 번째 Promise
})
.then(response => response.json()) // 다섯 번째 Promise
.then(posts => {
console.log(posts); // 여섯 번째 Promise
return fetch('https://json.site.com/comments'); // 일곱 번째 Promise
})
.then(response => response.json()) // 여덟 번째 Promise
.then(comments => {
console.log(comments); // 아홉 번째 Promise
})
.catch(error => {
console.error('Error occurred:', error); // 에러 처리
});
- 첫 번째 fetch 함수가 호출되어 Promise를 반환합니다.
- 첫 번째 then 메서드에서는 첫 번째 Promise의 결과인 response를 JSON 형식으로 파싱 하는 새로운 Promise를 반환합니다.
- 두 번째 then 메서드에서는 JSON 데이터를 처리하는 로직이 있고, 이후에 또 다른 HTTP 요청을 보내는 새로운 Promise를 반환합니다.
- 다음 then 메서드들도 이와 같은 방식으로 chaining 되어 순차적으로 실행됩니다.
- 마지막에 발생하는 에러는 catch 메서드에서 처리됩니다.
◼ Promise - then 상태
promise에는 총 3가지의 상태가 있다
pending => 작업 중
fullfiled => 성공
rejected => 실패
1. 실행 전
fetch('https://json.site.com/users')
.then((response) => response.json())
.then((result) => { console.log(result) });
2. 실행 후
[promise-pendung] fetch('https://json.site.com/users')
[promise-pendung] .then((response) => response.json())
[promise-pendung] .then((result) => { console.log(result) });
3. 실행 후 fetch (성공)
// 응답의 성공 .then((response) <== response 에 전달된다
[promise-fullfiled] fetch('https://json.site.com/users')
[promise-pendung] .then((1)(response) => response.json())
[promise-pendung] .then((result) => { console.log(result) });
4. 첫번째 .then 행동 (성공)
[promise-fullfiled] fetch('https://json.site.com/users')
// (1)번 (response) => response.json()=> [promise 성공 상태]가 되며,
// .then의 return promise 객체는 (1)번 같은 [promise 성공 상태] 전달 받아 바뀐다
[promise-fullfiled] .then((1)(response) => response.json())
[promise-pendung] .then((result) => { console.log(result) });
5. 두번째 .then 행동 (성공)
[promise-fullfiled] fetch('https://json.site.com/users')
[promise-fullfiled] .then((response) => response.json())
// 첫번째 .then promise 상태를 똑같이 가진다
[promise-fullfiled] .then((result) => { console.log(result) });
3. 실행 후 fetch (catch 예시, 실패)
// 응답의 성공 .then((response) <== response 에 전달된다
[promise-rejected] fetch('https://json.site.com/users')
[promise-pendung] .then((response) => response.json())
[promise-pendung] .then((result) => { console.log(result) })
[promise-pendung] .chtch((error) => { console.log(error) }); // 실패 실행
3. 실행 후 fetch (실패)
// 응답의 성공 .then((response) <== response 에 전달된다
[promise-rejected] fetch('https://json.site.com/users')
// (1)번은 (실패)시 실행되는 곳이다.
[promise-pendung] .then((response) => response.json(),(1)(error) => console.log(error))
[promise-pendung] .then((result) => { console.log(result) });
주의
- 리턴한 promise 객체가 문자, 숫자, 객체여도 fullfiled 상태가 되면서 문자, 숫자, 객체를 출력함
- 메소드(catch, then 등)에서 콜백이 실행되면아무 값도 return하지 않는기에, js는 아무값도 return 하지 않는 것을 undefined로 간주한다. 따라서 chach 메소드가 return한 promise객체는 fullfiled 상태가 되면서 'undefined'를 성공 결과로 가져오면서 ' undefined'를 출력함 (alert도!)
- 콜백 실행 중에 에러가 발생하면, then 메소드가 리턴한 Promise 객체는 rejected 상태가 되고, 그 작업 실패 정보로 해당 Error 객체를 갖게 된다는
◼ Promise - .finally
성공과 실패를 상관없이 항상 실행되었으면 할 때 실행하는 메소드이다.
데이터를 가져온 후에는 파일을 닫거나, 데이터베이스 연결을 종료등 상시 마지막에 성공여부에 상관없을 때 사용한다.
fetch('https://www.error.www')
.then((response) => response.text())
.then((result) => { console.log(result); })
.catch((error) => { console.log('Hello'); throw new Error('test'); })
.finally(() => { console.log('final'); }); // 상시 출력
'[노트장] 적으며 정리해 보는 이론 > 웹개발기본' 카테고리의 다른 글
[웹개발기본] async / await문 (0) | 2024.03.12 |
---|---|
[웹개발기본] Fetch (0) | 2024.03.11 |
[웹개발기본] HEAD Content-Type (0) | 2024.03.11 |
[웹개발기본] Request의 종류 (0) | 2024.03.11 |
[웹개발기본] 직렬화, 역직렬화 : 데이터를 다른 형식으로 (0) | 2024.03.11 |