본문 바로가기

Tech/[Lang] JS & TS

promise에 대해서

Hi, There!
안녕하세요, 바오밥입니다.


목차

  1. 개요
  2. 본문
  3. Reference

개요

자바스크립트의 프로미스 부분을 정리하였습니다.


본문

자바스크립트의 비동기 처리

자바스크립트는 비동기 처리란 특정 코드에 의해 실행된 연산이 종료되지 않았음에도 불구하고 다른 코드가 실행되는 특성을 말합니다.

 

자바스크립트의 비동기 처리 예시 - setTimeout

setTimeout은 이전 장에 잘 설명되어 있으니 참고 부탁드립니다.

스케쥴링 메서드 (setTimeout, setInterval)

코드의 흐름대로 실행되지 않고, 3초를 기다리는 동안 hello again이 미리 실행되어 버립니다.

console.log("hello!");
setTimeout(function(){
  console.log("bye!");
}, 3000);
console.log("hello again!");
/*
hello -> hello again -> bye
*/

 

콜백 함수

비동기 처리의 문제점을 해결하기 위해 콜백 함수를 사용합니다.

콜백 함수는 모든 연산이 종료된 이후에 다음 코드가 실행될 수 있도록 도와줍니다.

이를 통해 웹 서비스 제공 시 데이터가 준비된 시점에만 코드가 실행될 수 있도록 합니다.

만약, 콜백 함수가 없다면 데이터를 받아오기 전에 화면을 그리기 때문에 빈 화면이 뜨게 되는 현상이 발생합니다.

그러나 콜백 함수는 함수 내에서만 값을 유지할 수 있다는 단점이 있습니다. 또한, 콜백 함수를 여러 번 사용하다보면 콜백 지옥에 빠질 수 있습니다.

 

콜백 함수 예제 (콜백지옥)

const order1 = (cb) => {
  setTimeout(()=> {
    console.log("1번 주문 완료");
    cb();
  }, 3000);
}

const order2 = (cb) => {
  setTimeout(()=> {
    console.log("2번 주문 완료");
    cb();
  }, 2000);
}

const order3 = (cb) => {
  setTimeout(()=> {
    console.log("3번 주문 완료");
    cb();
  }, 1000);
}

console.log("시작")
order1(()=>{
  order2(()=>{
    order3(()=>{
      console.log("끝");
    })
  })
})

 

프로미스

프로미스는 콜백 함수의 단점을 보완한 함수입니다. 콜백 함수와 동일하게 비동기 처리의 문제점을 해결할 수 있습니다.

 

프로미스 예제

const pr = new Promise((res, rej) => {
  setTimeout(()=> {
    res("OK");
    // rej(new Error("err..."));
  }, 1000)
})

console.log("시작")
pr.then((result)=>{
  console.log(result);
})
.catch((err) => {
  console.log(err);
})
.finally(()=> {
  console.log("끝");
})

// "시작"
// 1초 후 "OK"
// "끝"

 

콜백 지옥을 프로미스 체이닝으로!

const order1 = () => {
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("1번 주문 완료");
    },1000)
  })
}

const order2 = (message) => {
  console.log(message)
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("2번 주문 완료");
    },3000)
  })
}

const order3 = (message) => {
  console.log(message)
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("3번 주문 완료");
    },2000)
  })
}

console.log("시작")
order1()
.then((res)=>order2(res))
.then((res)=>order3(res))
.then((res)=>console.log(res))
.catch(console.log)
.finally(()=>{
  console.log("끝")
})

 

만약 동시 주문을 하고 싶다면? Promise.all()

프로미스 체이닝을 사용하는 것보다 Promise.all()를 사용하는 것이 연산 속도가 더 빠릅니다.

다만, 프로미스 체이닝의 경우 reject 된 값까지 반환하는 반면, Promise.all()은 하나라도 reject 되면 값을 반환하지 않습니다.

하나의 정보라도 누락되면 페이지를 보여주면 안되는 경우 유용하게 사용될 수 있습니다.

const order1 = () => {
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("1번 주문 완료");
    },1000)
  })
}

const order2 = (message) => {
  console.log(message)
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("2번 주문 완료");
    },3000)
  })
}

const order3 = (message) => {
  console.log(message)
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("3번 주문 완료");
    },2000)
  })
}

console.log("시작")
Promise.all([order1(), order2(), order3()])
.then((res)=> {
  console.log(res)
// ["1번 주문 완료","2번 주문 완료","3번 주문 완료"] 반환
})

 

제일 먼저 완료된 애만 수행! Promise.race()

Promise.race()는 제일 먼저 완료된 애만 반환됩니다.

const order1 = () => {
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("1번 주문 완료");
    },1000)
  })
}

const order2 = (message) => {
  console.log(message)
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("2번 주문 완료");
    },3000)
  })
}

const order3 = (message) => {
  console.log(message)
  return new Promise((res,rej)=> {
    setTimeout(()=>{
      res("3번 주문 완료");
    },2000)
  })
}

console.log("시작")
Promise.race([order1(), order2(), order3()])
.then((res)=> {
  console.log(res)
// ["1번 주문 완료"] 반환
})

 


Reference

 

'Tech > [Lang] JS & TS' 카테고리의 다른 글

async, await에 대해서  (0) 2021.10.14
클래스  (0) 2021.10.07
상속과 프로토타입  (0) 2021.10.05
함수 호출 메서드 (call, apply, bind)  (0) 2021.09.27
스케쥴링 메서드 (setTimeout, setInterval)  (0) 2021.09.24