[Javascript] promise 객체

Hyoddin·2024년 5월 16일

Javascript

목록 보기
7/8

promise 객체

비동기 작업의 최종 완료 또는 실패를 나타내는 독자적인 객체입니다.
비동기 작업이 끝날 때까지 결과를 기다리는 것이 아닌, 결과를 제공하겠다는 약속을 반환한다는 의미에서 Promise라 명명 지어졌습니다.

등장 배경

callback hell이 발생한 코드를 promise 객체를 이용해 리팩토링하면, 비동기 작업의 개수가 많아져도 들여쓰기 코드의 깊이가 깊어지지 않게 됩니다.
이처럼, promise 객체를 사용하면 callback 함수를 대체하고, 비동기 작업의 흐름을 쉽게 제어할 수 있습니다.

promise 객체 사용법

promise 객체 생성

// 1️⃣
const myPromise = new Promise((resolve, reject) => {
	// 2️⃣
    const data = fetch('서버로부터 요청할 URL');
    
    // 3️⃣
    if(data)
    	resolve(data);
    // 4️⃣
    else
    	reject("Error"); 
})

1️⃣ promise 객체
Promise 생성자 안에는 두 개의 매개변수를 가진 콜백 함수(executor)를 넣습니다.
첫 번째 인수는 작업을 성공했을 때 성공임을 알려주는 객체입니다.
두 번째 인수는 작업이 실패했을 때 실패임을 알려주는 오류 객체입니다.

2️⃣ 비동기 작업 수행

3️⃣ 성공
비동기 작업이 성공하면, resolve() 함수를 호출합니다.

4️⃣ 실패
비동기 작업을 실패하면, reject() 함수를 호출합니다.

promise 객체 처리

promise 객체는 비동기 작업의 결과에 따라 .then().catch() method를 통해 성공과 실패에 대한 후속 처리를 진행합니다.

myPromise
    .then((value) => { // 1️⃣
    	console.log("Data: ", value); 
    })
    .catch((error) => { // 2️⃣
     	console.error(error); 
    })
    .finally(() => { // 3️⃣
 
    })

1️⃣ 비동기 작업의 성공
promise 객체 내부에서 resolve(data)를 호출합니다.
그 이후, 바로 .then()으로 이어져 then method의 콜백 함수에서 성공에 대한 추가 처리를 진행합니다.
이때 호출한 resolve() 함수의 매개변수의 값이 then method의 콜백 함수 인자로 들어가 then method 내부에서 promise 객체 내부에서 다룬 값을 사용할 수 있습니다.

2️⃣ 비동기 작업의 실패
promise 객체 내부에서 reject("Error")를 호출합니다.
그러면, .catch() 로 이어져 catch method의 콜백 함수에서 실패에 대한 추가 처리를 진행합니다.

3️⃣ 비동기 작업의 성공여부와 상관없이 실행되는 코드

promise 함수 등록

promise 객체를 변수에 바로 할당하는 방식을 사용할 수 있지만, 보통은 별도로 함수로 감싸서 사용하는 것이 일반적입니다.

promise 함수를 만들어 그 함수를 호출하면 promise 생성자를 return함으로서, 생성된 promise 객체를 함수 반환 값으로 얻어 사용하는 기법입니다.

// 1️⃣
function myPromise() {
  return new Promise((resolve, reject) => {
    if (/* 성공 조건 */) {
      resolve(/* 결과 값 */);
    } else {
      reject(/* 에러 값 */);
    }
  });
}

// 2️⃣
myPromise()
    .then((result) => {
      // 3️⃣
    })
    .catch((error) => {
      // 4️⃣
    });

1️⃣ promise 객체를 반환하는 함수 생성

2️⃣ promise 객체를 반환하는 함수 사용

3️⃣ 성공 시 실행할 콜백 함수

4️⃣ 실패 시 실행할 콜백 함수

promise 객체를 함수로 만드는 이유

1️⃣ 재사용성

promise 객체를 함수로 만들면 필요할때마다 호출하여 사용해 반복되는 비동기 작업을 효율적으로 처리할 수 있습니다.

2️⃣ 가독성

코드의 구조가 명확해지며, 비동기 작업의 정의와 사용을 분리하여 코드의 가독성을 높입니다.

3️⃣ 확장성

인자를 전달하여 동적으로 비동기 작업을 수행할 수 있습니다.
또한, 여러 개의 promise 객체를 반환하는 함수들을 연결하여 복잡한 비동기 로직을 구현할 수 있습니다.

대표적 사용 사례

fetch()


fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then((response) => response.json()) 
  .then((data) => console.log(data)); 

promise의 상태

Pending(대기) 상태

아직 비동기 처리 로직이 완료되지 않은 상태입니다.

Fulfilled(이행) 상태

비동기 처리 로직이 성공적으로 완료된 상태입니다.

Rejected(실패) 상태

비동기 처리 로직을 실패한 상태입니다.

promise 체이닝

promise handler를 연달아 연결하는 것을 말합니다.
이렇게 하면 여러 개의 비동기 작업을 순차적으로 수행할 수 있습니다.


then 핸들러에서 값을 리턴하면, 그 반환 값은 자동으로 promise 객체로 감싸져 반환됩니다.
그 후 다음 then 핸들러에서 반환된 promise 객체를 받아 처리합니다.

Promise Hell

promise의 then() method가 지나치게 체인되어 반복되면 코드가 장황해지고 가독성이 굉장히 떨어집니다.

// 1️⃣
fetch("https://api.github.com/users")
  .then((response) => {
    // 2️⃣
    if (response.ok) {
      return response.json();
    } else {
      throw new Error("Network Error");
    }
  })
  // 3️⃣
  .then((users) => {
    return users.map((user) => user.login);
  })
  // 4️⃣
  .then((logins) => {
    return logins.join(", ");
  })
  // 5️⃣
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

1️⃣ 유저 정보를 가져오기

2️⃣ 유저 정보를 JSON으로 가져오기

3️⃣ 유저들의 login 이름을 모으기

4️⃣ 유저들의 이름을 ,로 구분한 문자열로 만들기

5️⃣ 문자열 출력

then() method를 여러번 사용하면, 각 then method가 어떤 값을 반환하는지 파악하기 어렵습니다.
또한, catch method가 마지막에 한 번만 사용되어 중간에 발생하는 에러나 예외 상황에 대응하기 어렵습니다.


참고
📚 자바스크립트 Promise 개념 & 문법 정복하기

profile
공부일지로 완벽하지 않을 수 있습니다 🐹

0개의 댓글