본문 바로가기
목차
[노트장] 적으며 정리해 보는 이론/웹개발기본

[웹개발기본] Promise

by 졸린부엉이 2024. 3. 12.

 

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); // 에러 처리
  });

 

  1. 첫 번째 fetch 함수가 호출되어 Promise를 반환합니다.
  2. 첫 번째 then 메서드에서는 첫 번째 Promise의 결과인 response를 JSON 형식으로 파싱 하는 새로운 Promise를 반환합니다.
  3. 두 번째 then 메서드에서는 JSON 데이터를 처리하는 로직이 있고, 이후에 또 다른 HTTP 요청을 보내는 새로운 Promise를 반환합니다.
  4. 다음 then 메서드들도 이와 같은 방식으로 chaining 되어 순차적으로 실행됩니다.
  5. 마지막에 발생하는 에러는 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'); }); // 상시 출력