(JS) 모던 자바스크립트 : Promise

호두파파·2021년 3월 15일
0

호두파파 JS 스터디

목록 보기
23/27

모던 자바스크립트 비동기 프로그래밍 : Promise

가독성 개선과 에러핸들링 등과 같은 초창기 비동기 프로그래밍의 흐름을 효율적으로 개선하기 위한 고민은 현재까지 계속되고있다.

  • Promise
  • Async, Await
  • Genereator 등등..

이중
PromiseAsync / Await가 가장 대표적인 방법이라 할 수 있다.

Promise

Promise는 JavaScript 비동기 작업을 도와주는 객체로 비동기 작업의 상태와 결과, 에러 핸들링 등을 도와줄 수 있다.

Promise의 장점

  • 비동기 프로세싱의 가독성 향상
  • 획기적인 에러핸들링
  • 비동기 실행의 상태 확인
  • Promose 객체를 함수 인자로 넘길 수 있음

사실 많은 사람들이 Promise를 콜백지옥의 해결책이라 생각하지만, 그보다는 에러핸들링과 가독성 향상에 대한 이점을 갖는 방식이라고 봐야 한다.

Promise 사용법

Promise 객체 생성(비동기 작업 수행) - Pending

const promise = new Promise(function(resolve, reject) {
  // 작업 수행시 resolve() 호출
  // 에러 시 reject() 호출
})

프로미스 객체를 생성하면 곧바로 인자로 전달한 비동기 함수가 실행된다.
곧바로 호출되는 비동기 함수는 resolvereject라는 함수를 인자로 받아야한다. 위 코드에 인자로 받는 함수들은 대기상태인 Pending이 된다.

resolve() 호출 - Fullfilled

const promise = new Promise(function(resolve, reject) {
  setTimeout(() => {
    resolve(20)
  }, 3000)
})

promise.then(result => {
  console.log(result)
})
// 3초 뒤 20이 출력된다.

이처럼 비동기 작업을 완료 후에 resolve(결과값)으로 호출하면 Promise객체의 상태는 Fullfilled가 된다.
그리고 아래와 같이 then()을 통해 위 Promise객체 생성시 인자로 넣은 비동기 함수에서 호출한 resolve(결과값)을 콜백함수처럼 사용할 수 있다.

Promise.then(function calledResolve(result) {
  // resolve(결과값)으로 실행되는 콜백함수 
})

그리고 이 then()메서드를 호출하고 나면 새로운 프로미스 객체가 반환된다.

return 값은 다음 then 메서드 콜백함수의 결과로 전달

이를 통해 Promise Chaning이 가능해진다.

Promise 체이닝

프로미스의 특징은 여러개의 프로미스를 연결해서 사용할 수 있다.
then을 호출하면 새로운 Promise객체가 호출된다. 이를 통해 then()의 콜백함수에서 또 다시 비동기 호출을 할 수 있으면 return 값은 다음 then() 메서드 콜백함수의 결과로 전달된다.

new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve(1)
  }, 2000)
})
  .then(function(result) {
    console.log(result) // 1
    return result + 10
  })
  .then(function(result) {
    console.log(result) // 11
    return result + 20
  })
  .then(function(result) {
    console.log(result) // 31
  })

reject() 호출 - Rejected

const Promise = new Promise(function(resolve, reject) {
  setTimeout(() => {
    reject(new Error('reject 호출'))
  }, 1000)
  
  setTimeout(() => {
    resolve(20)
  }, 3000)
})

promise
  .then(result => {
    console.log(result)
  })
  .catch(err => {
    console.log(err)
  })
// 1초 뒤 Error : reject 호출 출력 

위와 같이 reject(에러)로 호출하면 Promise 객체의 상태는 Rejected가 된다. 그리고 아래와 같이 catch를 통해 위 Promise 객체 생성시 인자로 넣은 비동기함수에서 호출한 reject(에러)를 콜백함수처럼 사용할 수 있다.

Promise.catch(function calledReject(err) {
  // reject (err)으로 실행되는 콜백함수 
})

Promise의 예외처리

비동기 처리 중에 알 수 없는 애러처리가 발생해서 reject도 못쓰는 경우가 발생하면 어떻게 될까?

const promise = new Promise(function(resolve, reject) {
  setTimeout(() => {
    resolve(20)
  }, 3000)
})

getData()
  .then(function(result) {
  	console.log(result) // 3초 뒤 20 출력 
  	throw new Error('첫번째 then에서 알 수 없는 에러 발생!') // 첫번째 then에서 에러 발생 
  .catch(function(err) {
    console.log(err) // Error : 첫번째 thedn에서 알 수 없는 에러 발생! 출력
  })

이 처럼 catch()를 이용하면 비동기 처리 중에 알 수 없는 에러처리가 발생하더라도 에러 핸들링을 할 수 있다.
또 4번에서 봤던 Promise Chaning으로 이루어진 비동기 처리라하더라도 catch만 쓴다면 어떤 then()에서 reject()나 알 수 없는 에러가 발생하더라도 모두 catch()가 가능해지는 우아한 비동기 에러 핸들링이 가능해진다.

Promise 객체를 인자로 전달

Promise 객체는 javaScript에서 Object타입으로 1급 객체이다.
이 말인 즉슨 함수의 인자값으로 전달 가능하다는 말이다.

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(30)
  }, 3000)
})

function func(promiseProp) {
  let value = 100
  promiseProp
  	.then(result => {
      console.log(result)
      console.log(100)
  	})
  	.catch(err => {
      console.log(err)
  })
}
func(promise) //promise객체를 인자로 전달 

이처럼 프로미스 객체를 다른 함수로 전달해 그 함수의 함수 스코프를 이용한 콜백처리가 가능해진다.

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글