[JavaScript] promise

빵호·2022년 1월 5일
0

JavaScript

목록 보기
23/28
post-thumbnail

promise

프로미스를 사용하면 비동기 프로그래밍을 할 때 동기 프로그래밍 방식을 코드를 작성할 수 있다.

콜백 패턴의 문제

ES6에 프로미스가 추가되기 전에는 콜백(callback) 패턴을 많이 사용했었다. 하지만 콜백 패턴은 콜백이 조금만 중첩돼도 코드가 상당히 복잡해지는 단점이 있다.

function requestData1(callback) {
  //...
  callback(data); // 2
}
function requestData2(callback) {
  //...
  callback(data); // 4
}
function onSuccess1(data) {
  console.log(data);
  requestData2(onSuccess2); // 3
}
function onSuccess1(data) {
  console.log(data); // 5
  //...
}
requestData1(onSuccess1); // 1

콜백 패턴은 코드의 흐름이 순차적이지 않기 때문에 코드를 읽기 상당히 힘들다. 하지만 프로미스를 사용하면 코드가 순차적으로 실행되게 작성할 수 있다.

프로미스의 상태

  1. 대기 중(pending) : 결과를 기다리는 중
  2. 이행됨(fulfilled) : 수행이 정상적으로 끝났고 결과값을 가지고 있음
  3. 거부됨(rejected) : 수행이 비정상적으로 끝났음

프로미스는 세 가지 상태 중 하나의 상태로 존재하고 이행됨, 거부됨 상태를 처리됨(settled) 상태라고 부른다. 프로미스는 처리됨 상태가 되면 더 이상 상태 변경이 되지 않는다.

프로미스를 생성하는 방법

const p = new Promise((resolve, reject) => {
// ...
// resoleve(data)
// or reject('error message')
});

new 키워드를 사용해서 프로미스를 생성한다. 생성된 프로미스의 초기 상태는 대기 중 상태이고 resolve와 reject라는 콜백 함수를 매개변수로 갖는다. 비동기 작업을 수행 후 성공했을 때 resolve를 호출하고, 실패했을 때 reject를 호출하면 된다. resolve를 호출하면 p 객체는 이행됨 상태가 되고 reject를 호출하면 거부됨 상태가 된다. new 키워드로 생성된 프로미스는 생성되는 순간 실행된다.

후속 처리

then, catch

request()
.then(data => {
 console.log(data);
})
.catch(error => {
  console.log(error);
});

then은 처리됨 상태가 된 프로미스를 처리할 때 사용되는 메서드이고 항상 프로미스를 반환하기 때문에 연속적으로 then 메서드를 호출할 수 있다.

catch는 프로미스 수행 중 발생한 예외를 처리하는 메서드이고 then과 마찬가지로 catch 메서드도 새로운 프로미스를 반환한다.

Promise.reject(10)
.then(data => {
  console.log('then1:', data);
  return 20;
})
.catch(error => {
  console.log('catch', error);
  return 30;
})
.then(data => {
  console.log('then2', data);
});
// catch: 10;
// then2: 30

따라서 catch 메서드 이후에도 then 메서드를 사용할 수 있다.

finally

finally는 프로미스가 이행됨, 거부됨 상태일 때 호출되는 메서드이다.

requestData()
.then(data => {
  // ...
})
.catch(error => {
  // ...
})
.finally(data => {
  // ...
});

finally 메서드는 프로미스 체인의 가장 마지막에 사용하면 되고 이전에 사용된 프로미스를 그대로 반환한다. 따라서 처리됨 상태인 프로미스의 데이터를 건드리지 않고 추가 작업을 할 때 사용될 수 있다.

프로미스 활용

Promise.all

Promise.all은 여러 개의 프로미스를 병렬 처리할 때 사용하는 함수이다.

Promise.all([requestData1(), requestData2()]).then(([data1, data2]) => {
  console.log(data1, data2);
});

Promise.all 함수도 프로미스를 반환하는데 주의할 점은 입력된 모든 프로미스 중 하나라도 거부됨 상태가 된다면 Promise.all 함수가 반환하는 프로미스도 거부됨 상태가 된다.

Promise.race

Promise.rac는 여러 개의 프로미스 중에서 가장 빨리 처리된 프로미스를 반환하는 함수이다.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"

Promise.race 함수에 입력된 프로미스 중에서 하나라도 처리됨 상태가 되면, Promise.race 함수가 반환하는 프로미스도 처리됨 상태가 된다.

profile
늘 한결같이 꾸준히

0개의 댓글