2 분 소요



📖Promise

프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용합니다. 일반적으로 웹 애플리케이션을 구현할 때 서버에서 데이터를 요청하고 받아오기 위해 아래와 같은 API를 사용합니다.

axios.get("/api/memos").then((res) => {
  // backend 서버에서 memos데이터를 받아왔습니다.
  state.data = res.data;
});

JsCopy 위 API가 실행되면 서버에다가 ‘데이터 하나 보내주세요’ 라는 요청을 보내죠. 그런데 여기서 데이터를 받아오기도 전에 마치 데이터를 다 받아온 것 마냥 화면에 데이터를 표시하려고 하면 오류가 발생하거나 빈 화면이 뜹니다. 이와 같은 문제점을 해결하기 위한 방법 중 하나가 프로미스입니다.

Promise는 자바스크립트의 내장되어있는 객체입니다. 비동기적인 수행할때 콜백 함수를 대신해서 유용하게 사용할수 있습니다.

프로미스는 두가지 포인트가 있습니다.

  • State

    상태. 프로세스가 무거운 operation을 수행하고 있는 중인지, 아니면 기능수행이 완료되어서 성공했는지, 실패했는지 같은 상태에 대해 이해하는 것이 중요합니다.

  • producer와 consumer의 차이

    원하는 데이터를 제공하는 사람(producer)과, 제공된 데이터를 소비하는 사람의 두 다른 견해를 이해하는 것이 중요합니다.

📖Producer

promise는 클래스이기 때문에 new라는 키워드를 이용해서 객체를 생성할수 있습니다. promise의 생성자를 보면 executor라는 콜백함수를 전달해줘야합니다. 그리고 또 다른 2가지의 콜백함수를 받습니다. resolve,reject 입니다.

보통은 promise안에서는 무거운 일들을 합니다. 네트워크에서 데이터를 받아오거나 파일에서 큰 데이터를 읽어오는 과정은 시간이 걸립니다. 그런걸 동기적으로 처리하게되면 파일을 읽어오고 네트워크에서 데이터를 받아오는 동안 그 다음 라인의 코드가 실행되지 않기 때문에 시간이 조금 걸리는 일들은 promise를 이용해서 비동기로 처리하는것이 좋습니다.


const promise = new Promise((resolve, reject) => {
  // doing some heavy work (network, read files)
  console.log("doing something...");

  setTimeout(() => {
    // 2초뒤에 기능이 잘 작동했다면 resolve를 통해 받아오거나 읽어온 데이터를 전달합니다.
    resolve("ellie");
  }, 2000);
});


📖Consumers: then, catch, finally

Producer에서 promise를 만들었다면 이제 사용해보겠습니다. 아래 예제 에서의 then은 promise가 정상적으로 잘 작동되어서 setTimeout 메서드에서 resolve로 전달된 값이 value 파라미터를 통해 전달되었습니다.

만약 데이터 전송이 실패했거나 네트워크에 문제가 생겼을때에는 reject를 이용해서 error를 전달합니다.

reject는 보통 Error 객체를 사용해서 에러 메시지를 보냅니다. 그다음 catch를 이용해서 에러 메시지를 받습니다.

마지막으로 finally를 알아보겠습니다. 성공과 실패 상관없이 무조건 마지막에 실행되는 기능입니다.

const promise = new Promise((resolve, reject) => {
  // doing some heavy work (network, read files)
  console.log("doing something...");

  setTimeout(() => {
    // 2초뒤에 기능이 잘 작동했다면 resolve를 통해 받아오거나 읽어온 데이터를 전달합니다.
    resolve("ellie");

    //resolve가 잘 작동하지 않았을 경우 reject의 오류가 아래 catch로 전달됩니다.
    reject(new Error("no network"));
  }, 2000);
});

promise
  .then((value) => {
    console.log(value);
    // 2초뒤 "ellie"
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("finally");
  });



📖 Error Handling 오류 처리

예제를 통해 오류를 처리해보겠습니다.



//오류 없이 잘 작동하는 예제입니다.
const getHen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve("🐔"), 1000);
  });

const getEgg = (hen) =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${hen} => 🥚`), 1000);
  });

const cook = (egg) =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => 🍳`), 1000);
  });

// 빋이오는 값이 다른함수에 넣어 호출할때에는 축약형으로 작성할수 있습니다.
// .then(hen => getEgg(hen))을 .then(getEgg)로 축약할수 있습니다. 암묵적으로 getEgg에 값을 전달하여 호출합니다.
getHen() //
  .then(getEgg)
  .then(cook)
  .then(console.log);

// 3초뒤 🐔 => 🥚 => 🍳

//------------------------------------------

// 위 코드에 에러를 만들어 보겠습니다.
// getEgg에 닭이 전달되지 않고 에러가 발생하는 코드입니다. 이럴때는 오류가 발생하는 then 바로 뒤에 catch를 이용하여 return 원하는 값을 넣어줘서 이어가게 할수 있습니다.

const getHen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve("🐔"), 1000);
  });

const getEgg = (hen) =>
  new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error(` error! ${hen} => 🥚`)), 1000);
  });

const cook = (egg) =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => 🍳`), 1000);
  });

// 빋이오는 값이 다른함수에 넣어 호출할때에는 축약형으로 작성할수 있습니다.
// .then(hen => getEgg(hen))을 .then(getEgg)로 축약할수 있습니다. 암묵적으로 getEgg에 값을 전달하여 호출합니다.
getHen() //
  .then(getEgg)
  .catch((errer) => {
    return "🌭";
  })
  .then(cook)
  .then(console.log)
  .catch(console.log);

//3초뒤 🌭 => 🍳

댓글남기기