티스토리 뷰

이번에 비동기 처리와 콜백 함수의 사용법을 알아보았습니다.

하지만 콜백 함수를 여러 번 반복해서 쓰게 되면 가독성이 너무 떨어지고 콜백 지옥을 경험할 수 있습니다.

그래서 우리를 위해 존재하는 것이 Promise입니다. 기능은 콜백 함수와 같기 때문에 콜백 함수를 이해하셨다면 promise도 쉽게 이해하실 것 같아요!

 

콜백 함수가 헷갈린다면 콜백 함수 포스팅이 준비되어 있습니다.👇

https://hiolivia.tistory.com/42

 

우선 promise의 기본 사용법은 아래와 같습니다.

const promise = new Promise((resolve, reject) => {});

 

resolve : 비동기 작업이 성공했을 때 실행시킬 콜백 함수

reject : 비동기 작업이 실패했을 때 실행시킬 콜백 함수

 

그렇다면 이 작업이 성공하거나 실패했을 때 어떤 동작을 시킬 것인지 정해줘야겠죠? 다음과 같이 하시면 됩니다.

const promise = new Promise((resolve, reject) => {
    resolve();
});

promise
    .then(()=>{
        console.log('성공!');
    })
    .catch(()=>{
    	console.log('실패!');
    })
    .finally(()=>{
    	console.log('완료!');
    })
    
//성공!
//완료!

then : resolve(성공)시에 실행시킬 함수

catch : reject(실패)시에 실행시킬 함수

finaaly : 성공이든 실패든 작업이 완료되면 실행시킬 함수

 

이것이 promise의 사용법입니다. 앞서 콜백 함수 포스팅에서 다뤘던 예제를 재사용해보겠습니다.

const profile = new Promise((resolve, reject) => {
      setTimeout(() => {
        let name = "olly";
        if (name) {
          resolve(name);
        } else {
          reject(new Error("no found"));
        }
      }, 2000);
    });

profile
  .then((name) => console.log(name))
  .catch((erorr) => console.log(error))
  .finally(() => console.log("All the tasks are finished"));
  
//실행결과
//olly
//All the tasks are finished

현재 예제에는 데이터를 가져오는 코드가 없지만 서버에서 많은 데이터를 가져오는데 2초가 걸린다고 가정하고, 대신 setTimeout() 함수로 비슷하게 구현해보겠습니다.

name이라는 변수에 데이터가 잘 담겼으면 resolve를, 아니라면 no found라고 에러를 띄우는 코드입니다.

 

한 가지 더 살펴보겠습니다. 만약 파라미터로 어떤 값을 promise 함수로 보내야 한다면 매번 new Promise() 이런식으로 선언해야 할까요? 그렇지 않습니다. 함수를 만들어 promise를 리턴하게 만들어주면 됩니다.

const promise = (id) =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
          let info = {
            id: id,
            name: "olly",
          };
          if (info) {
            resolve(info);
          } else {
            reject(new Error("info is unavailable"));
          }
        });
      });
    }

promise(10)
  .then((val) => console.log(val))
  .catch((error) => console.log(error))
  .finally(() => console.log("First task finished"));

promise(20)
  .then((val) => console.log(val.id))
  .catch((error) => console.log(error))
  .finally(() => console.log("Second task finished"));
  
  
//실행결과
//{id: 10, name: 'olly'}
//First task finished
//20
//Second task finished

다음은 promise chaining인데, 작업 성공 후 then을 사용해 여러 개의 작업을 해주는 것입니다.

const chaining = new Promise((resolve, reject) => {
  setTimeout(() => {
    let num = 1;
    resolve(num);
  }, 1000);
});
chaining
  .then((num) => num + 1) //2
  .then((num) => num + 2) //4
  .then((num) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(num * 2), 1000);
    });
  })
  .then((num) => console.log(num)); //8

then에는 새로운 promise를 리턴해줄 수도 있습니다. 만약 처음 promise에서 num 변수에 데이터를 담은 후, 두번째 promise에서 서버에게 어떤 데이터를 요청한 결과 num에 다른 데이터가 담겨야 한다면 저런 식으로 구현하면 됩니다. 그래서 최종 num의 값은 8입니다.

 

이해를 도왔던 엘리님의 코드를 복사해왔습니다. (유튭 드림코딩 강추합니다 엘리쌤 최고에요....💜)

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);
  });
  
getHen()
  .then((hen) => getEgg(hen))
  .catch((error) => {
    return "🍌";
  })
  .then((egg) => cook(egg))
  .then((meal) => console.log(meal));
  
  
  //에러가 없었으면
  //🐓 => 🥚 => 🍳
  
  //실행결과
  //🍌 => 🍳

 

promise 알고보니 어렵지 않습니다! 다음 포스팅은 async/await로 돌아오겠습니다.👋