프로미스(promise)

succeeding·2022년 6월 15일
1

JavaScript 베이스

목록 보기
4/6

1. 프로미스란?

Promsie는 비동기 작업의 상태(이행이나 실패)와 그 결과 값(실패의 경우 error)을 나타내는 객체

  • promise(약속)라는 단어 속에는 비동기 작업의 결과를 미래의 어떠한 시점에 제공하겠다는 약속의 의미가 담김

    • 비동기 작업의 결과를 받게 되는 그 미래의 시점 이후, 해당 결과(결과 값이나 에러)를 처리하는 작업을 에러 없이 코딩할 수 있음
  • 이를 통해 비동기 메서드를 마치 동기 메서드처럼 다룰 수 있게 됨

    • 예를 들어, 외부 스크립트에 담긴 특정 함수를 사용하기 위한 코드를 짜는 경우
      • 외부 스크립트를 읽어오는 작업은 비동기 작업이다.
      • 읽는 코드 바로 다음에 특정 함수를 사용하는 코드를 작성시, 아직 읽어오는 비동기 작업이 끝나지 않아서 에러가 발생할 수 있다.
      • 이를 promise를 사용하여 동기화 시켜서 읽어온 후에 특정 함수를 사용하는 코드가 실행되게끔 할 수 있다
  • callback hell현상을 극복할 수 있는 문법

    • callback hell이란 콜백 함수의 중첩으로 가독성이 떨어지고 리팩토링이 어려워지는 현상

2. 문법

let promise = new Promise(function(resolve, reject) {
// 시간이 걸리거나 비동기 작업에 대한 코드
  
// resolve나 reject를 호출하는 코드
})

executor(실행자, 실행 함수)

new Promise에 전달되는 함수

  • new Promise가 실행될 때 자동 실행됨
  • 주로 시간이 걸리거나 비동기 작업에 대한 코드가 있음
  • 인수로 resolvereject라는 JS가 자체 제공하는 콜백함수를 가짐
    • resolve(value): 작업이 성공적으로 완료 경우 호출됨
    • reject(error): 작업 중 에러가 발생한 경우 호출됨

Promise의 속성(property)

객체 promise는 다음 두 가지의 private 속성을 가짐

  • state
    • fulfilled: 작업이 성공적으로 완료됨
    • rejected: 작업 실패
    • pending: 작업이 완료되기 전 상태
  • result
    • value: resolve의 인수
    • error: reject의 인수

3. Promise의 메서드

executor의 작업이 끝난 후(status of [fulfilled, rejected])에 Promise객체의 private 속성 state, result에 접근하여 비동기 작업 이후의 동작을 코딩할 수 있게 해줌

then

promise.then(
  function(result) { /* status가 fulfilled일 때의 result인 value를 다룸 */ },
  function(error) { /* status가 rejected일 때의 result인 error를 다룸 */ }
)
  • .then(f): 성공한 경우만 다루는 경우
  • .then(null, f): 실패한 경우만 다루는 경우

catch

.catch(f) == .then(null, f)

finally

fullfilled이거나 rejected이거나 반드시 실행됨

  • 쓸모가 없어진 로딩 인디케이터(loading indicator)를 멈추는 것과 같이, 어떠한 경우에든 마무리가 필요한 작업에 대해 유용함

4. 활용

1) 콜백 중첩 줄이기

  • 콜백 중첩이 사용된 경우
function callbackHell() {
    setTimeout(() => { // 첫 번째 콜백
        let result = 1
        alert(result)

        setTimeout(() => { // 두 번째 콜백
            result *= 2
            alert(result)

            setTimeout(() => { // 세 번째 콜백
                result *= 2
                alert(result)
            }, 1000)
        }, 1000)
    }, 1000)
}
  • promise 문법을 사용한 경우
    • 깊이가 일정하여 가독성 향상
function usePromise() {
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(1), 1000)
    })
      .then(result => {
          alert(result)
          return new Promise((resolve, reject) => {
              setTimeout(() => resolve(result * 2), 1000)
          })
      })
      .then(result => {
          alert(result)
          return new Promise((resolve, reject) => {
              setTimeout(() => resolve(result * 2), 1000)
          })
      })
      .then(alert)
}

2) 여러 개의 Promise 한 번에 처리하기

const promise1 = Porise.resolve('성공1')
const promise1 = Porise.resolve('성공2')
Promise.all([promise1, promise2])
  .then((result) => {
    console.log(result) // ['성공1', '성공2']
  })
  .catch((error) => {
    console.error(error)
  })
  • Promise.all(), Promise.allSetteld(), Promise.any()을 사용하면 여러 개의 Promise 처리를 한 번에 할 수 있고 코드가 간결해짐
    • Promise.all()은 여러 개의 프로미스를 처리하면서 하나라도 실패하면 빠져나옴.
    • Promise.allSetteld()은 모든 프로미스를 끝까지 처리하고 실패한 프로미스를 추적 가능
    • Promise.any()은 하나의 프로미스라도 성공하면 빠져나옴

참고 자료

0개의 댓글