본문 바로가기

자바스크립트

[javaScript] 프로미스(Promise)에 대해 알아보았다(1)ㅣstate 프로퍼티 까지만

반응형

프로미스를 쓰는 이유와 형식

우리가 비동기적으로 코드를 작성하다 보면 함수 안의 함수, 그 함수 안의 함수, 또 그 함수 안의 함수 ....... 형태로 중첩되는 방향으로 콜백함수를 매개변수로 사용할 수 있는데, 이를 보통 콜백 지옥(Callback Hell) 이라 부른다고 하더라.

 

이런 코드들은 결국 코드의 들여쓰기가 마치 > 요런 모양으로 깊어지니까 본인 포함해서 다른 사람이 이 코드를 본다면 혼란에 빠질 수 있고, 무엇보다 유지보수에 치명적이기 때문에 이를 보완하여 비동기로 처리하는 시점을 명확히 할 수 있는 객체가 바로 Promise 라고 한다.

Promise는 ES2015 에 처음으로 등장했다고 하는데, 내가 코딩 공부를 시작한게 올해 반년 뒤였으니 엄청 오래되었네.

Promise는 비동기적 처리 시점을 명확히 할 수 있고, 그렇게 처리된 비동기적 작업이 성공 혹은 실패했으냐에 따라 다른 결과를 전달할 수 있게 하는 매개변수로 resolve( ) reject() 함수를 가지게 된다.

또한 Promise객체 이기 때문에 Promise 생성자 함수를 통해 인스턴스(실제 사용되는 객체)가 만들어지고, 생성자 함수 내에 전달 되는 함수를 실행자(executor) 라고 한다.

여기서 실행자는 resolve 와 reject 함수 중 무조건 하나는 호출해야 하고, 한 실행자 내에서 각 함수는 중복해서 호출하면 무시된다.


요약하자면 요런 형태

 const promise = new Promise((resolve, reject) =>{
  //실행자
  resolve(11) // -> 요넘 호출
  resolve(22) //-> 요넘 무시
  
  // 그 외 비동기 작업 수행 코드

프로미스 객체는 3가지 state 프로퍼티(속성)을 가진다.

프로미스는 3가지 상태를 나타내는 속성을 가진다. 이는 이행(fullfiled), 거부(reject), 보류(pending) 로 각각 성공, 실패, 작업의 실패/성공도 아닌 초기단계(보류상태)를 의미한다.

아래 예시를 통해 해당 조건문을 1초 뒤에 실행해보면 보류 상태가 뜨는 것을 확인할 수 있다(즉, 비동기적으로 실행되는 코드 이므로 이를 처리하기 위해 따로 빼놓는 것이다).

보류 상태는 프로미스 생성자 함수 내에서 실행된 코드가 다음 단계(이행, 거부) 되기 전의 초기 단계(시간이 걸려서, 잠시 보류된 상태)

향후 보류상태의 코드가 처리되면 3가지 state 프로퍼티를 통해서 이행 및 거부 상태로 나아가는데, 이행 상태가 되면 코드의 결과값이 result 로 전달된다.

 

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    let num = 100;

    if (num > 50) {
      resolve("num이 더 크다");
    } else {
      reject(new Error('에러임 처음봄?'));
    }
  }, 1000);
});

console.log(promise);

// 출력결과 )  Promise { <pending> }


이렇듯, 프로미스는 3 가지 상태 값을 가지는 데 이를 그냥 두는 것이 아니라 각 상태에 따라서 처리할 수 있는 메서드가 있다(즉, pending 은 다음 단계인 이행과 거부 단계로 가기 전에 오래걸릴 것 같으니 잠시 보류해둔 상태인 것이다).

 

프로미스 객체는 상태처리를 위해 then(), catch(), finally() 메서드를제공한다.

앞서 정리했던 보류(pending) 단계에 머물고 있는 코드를 이행(fullfiled), 거부(reject) 중 하나의 결과로 처리하기 위해  then, catch, finally 라는 메서드를 제공한다.

 

○ promise. then( 결과처리콜백, 에러처리콜백 )

then( ) 메서드는 결과와 에러를 같이 처리하거나, 에러자리는 비워두고 결과만 처리하거나, 결과에는 null을 전달하고 에러만 따로 처리하는 방식이 있다.

참고로 result 자리에는 앞서 promise 생성자 함수 내에서 작성한 코드의 결과값이 전달된다.

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

//대략적인 형식은 다음과 같은데, then(결과, 에러)와 같이 매개변수를 가진다.
promise.then((result)=>{ }, (error)=>{ });


//결과만 다룰 때 then() 메서드 는 error 자리는 비워두기만 하면 된다.
promise.then((result)=>{ });


//만일 error 처리만 다루고자 한다면?
promise.then(null,(error)=>{ });

 

○ promise. chatch( 에러처리 콜백)

앞서 살펴본 then() 메서드에서 에러만 따로 처리하는 방식과 같은데, 에러처리를 위한 콜백함수만 매개변수로 받기 때문에 보다 더 명시적이고 간결한 처리가 가능한 장점이 있다.

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


// then() 메서드 에러 처리
promise.then(null,(error)=>{ });


//catch() 메서드 에러처리(매개변수로 에러를 처리하는 콜백 함수만 받는다)
promise.catch((error)=>{ });

 

○ promise. finally( 이행, 거부 상태 관계없이 실행할 콜백함수)

마지막으로 finally () 메서드는 이행, 거부와 상관없이 작업을 수행하고자 할 때 사용되는 메서드이다. 보통 작업이 종료되었을 때, 필요한 공통적인 처리 작업을 수행할 때 활용한다.

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


promise.finally( () =>{

  //이행, 거절 상관없이 수행할 작업 코드 
  
  }). then((result) =>{
  
  //작업을 수행하고 전달할 결과로서 finally 메서드를 통해 전달된다.
  // ex) console.log(result)
  
  } ;
  
  
  //      --------------------------------------------------
 
 // 다음 코드를 실행해보면 1초 뒤에 '오오', 'num이 더 크다' 가 순서대로 출력된다.
 
 const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    let num = 100;

    if (num > 50) {
      resolve("num이 더 크다");
    } else {
      reject(new Error('아닌데'));
    }
  }, 1000);
});

promise.finally(()=>{
  console.log('오오') //작업의 성공과 실패 상관없이 1초 뒤에 그냥 실행되었다.
}).then((result)=>{
  console.log(result) // 요넘은 이행상태가 되어서 실행된 결과값이다.
})

//출력결과 )

/*오오
num이 더 크다 */

 

반응형