JS Promise란

2020. 1. 14. 17:57JAVASCRIPT

Promise는 JS 비동기 처리에 사용되는 객체입니다.

여기서 JS 비동기 처리란 '특정 코드의 실행이 완료될 때까지 기다리지않고 다음 코드를 먼저 수행하는 JS의 특징'을 의미합니다.

프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 떄 사용합니다.

 

Promise 예제 코드

function getData(callbackFunc) {
  $.get('url 주소/products/1', function (response) {
    callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
  });
}

getData(function (tableData) {
  console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});

위 코드는 제이쿼리의 ajax 통신을 이용하여 지정한 url에서 1번 상품 데이터를 받아오는 코드입니다. 비동기 처리를 위해 프로미스 대신에 콜백 함수를 이용했습니다.

function getData(callback) {
  // new Promise() 추가
  return new Promise(function (resolve, reject) {
    $.get('url 주소/products/1', function (response) {
      // 데이터를 받으면 resolve() 호출
      resolve(response);
    });
  });
}

// getData()의 실행이 끝나면 호출되는 then()
getData().then(function (tableData) {
  // resolve()의 결과 값이 여기로 전달됨
  console.log(tableData); // $.get()의 reponse 값이 tableData에 전달됨
});

콜백 함수로 처리하던 구조에서 new Promise(), resolve(), then()와 같은 프로미스API를 사용한 구조로 바뀌었습니다.

 

프로미스의 3가지 상태(states)

프로미스를 사용할 떄 알아야 하는 가장 기본적인 개념이 바로 프로미스의 상태(states)입니다. 여기서 말하는 상태란 프로미스의 처리 과정을 의미합니다. new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖습니다.

- pending(대기): 비동기 처리 로직이 아직 완료되지 않은 상태

- Fullfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태

- Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태

 

Pending(대기)

new Promise() 메서드를 호출하면 Pending(대기) 상태가 됩니다. 호출할 떄 콜백 함수의 인자로 resolve, reject에 접근 할 수 있습니다.

new Promise(function (resolve, reject) {
  // ...
});

Fullfilled(이행)

resolve()를 실행하면 Fullfilled(이행) 상태가 됩니다. 그리고 이행 상태가 되면 then()을 이용하여 처리 결과 값을 받을 수 있습니다.

function getData() {
  return new Promise(function (resolve, reject) {
    var data = 100;
    resolve(data);
  });
}

// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function (resolvedData) {
  console.log(resolvedData); // 100
});

Rejected(실패)

new Promise()로 프로미스 객체를 생성하면 콜백 함수 인자로 resolve와 reject를 사용할 수 있다고 했습니다. 여기서 reject 인자로 reject() 메서드를 실행하면 Rejected(실패)상태가 됩니다. 그리고, 실패 상태가 되면 실패한 이유를 catch()로 받을 수 있습니다.

function getData() {
  return new Promise(function (resolve, reject) {
    reject(new Error("Request is failed"));
  });
}

// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function (err) {
  console.log(err); // Error: Request is failed
});

프로미스 코드 - 예제

function getData() {
  return new Promise(function (resolve, reject) {
    $.get('url 주소/products/1', function (response) {
      if (response) {
        resolve(response);
      }
      reject(new Error("Request is failed"));
    });
  });
}

// Fulfilled 또는 Rejected의 결과 값 출력
getData().then(function (data) {
  console.log(data); // response 값 출력
}).catch(function (err) {
  console.error(err); // Error 출력
});

위 코드는 서버에서 제대로 응답을 받아오면 resolve() 메서드를 호출하고, 응답이 없으면 reject() 메서드를 호출하는 예제입니다. 호출된 메서드에 따라 then()이나 catch()로 분기하여 데이터 또는 오류를 출력합니다.

프로미스 에러 처리는 가급적 catch()로

// then()의 두 번째 인자로는 감지하지 못하는 오류
function getData() {
  return new Promise(function (resolve, reject) {
    resolve('hi');
  });
}

getData().then(function (result) {
  console.log(result);
  throw new Error("Error in then()"); // Uncaught (in promise) Error: Error in then()
}, function (err) {
  console.log('then error : ', err);
});

getData() 함수의 프로미스에서 resolve() 메서드를 호출하여 정상적으로 로직을 처리했지만, then()의 첫 번째 콜백 함수 내부에서 오류가 나는 경우 오류를 제대로 잡아내지 못합니다.

하지만 똑같은 오류를 catch()로 처리하면 다른 결과가 나옵니다.

// catch()로 오류를 감지하는 코드
function getData() {
  return new Promise(function (resolve, reject) {
    resolve('hi');
  });
}

getData().then(function (result) {
  console.log(result); // hi
  throw new Error("Error in then()");
}).catch(function (err) {
  console.log('then error : ', err); // then error :  Error: Error in then()
});

발생한 에러를 성공적으로 콘솔에 출력합니다. 따라서, 더 많은 예외 처리 상황을 위해 프로미스의 끝에 가급적 catch()를 붙이는 것을 권장합니다.

'JAVASCRIPT' 카테고리의 다른 글

JS 이벤트 위임하기  (0) 2020.01.14
JS async & await  (0) 2020.01.14
jQuery를 이용한 탭 메뉴 기능  (0) 2020.01.12
JS를 이용한 가위바위보 게임  (0) 2020.01.10
동기와 비동기  (0) 2020.01.09