Front-end/JavaScript

[JavaScript]프라미스 체이닝

Nave 2022. 11. 14. 01:27

순차적으로 처리해야 하는 로직이 여러개 있다면 어떻게 해야할까?

--> 프라미스 체이닝을 이용할 수 있다.

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

  alert(result); // 1
  return result * 2;

}).then(function(result) { // (***)

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

위의 프라미스 체이닝은 다음과 같은 순서로 실행된다.

  1. 1초 후 최초 프라미스가 이행된다. – (*)
  2. 이후 첫번째 .then 핸들러가 호출된다. –(**)
  3. 2에서 반환한 값은 다음 .then 핸들러에 전달된다. – (***)

또한 result가 핸들러 체인을 따라 전달되므로, alert 창엔 1, 2, 4가 순서대로 출력된다.

프라미스 체이닝이 가능한 이유는 promise.then을 호출하면 계속 프라미스가 반환되기 때문에 계속해서 그 프라미스에 .then을 이어서 호출할 수 있기 때문이다.

더보기

❌여기서 잠깐❌

프라미스 하나에 여러개의 .then을 추가한 것은 프라미스 체이닝이 아니다.

이건 그냥 프라미스 하나에 등록된 핸들러가 여러개인 것이다. 이 ,.then로직들은 순차적으로 처리되지 않고 독립적으로 처리된다.

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function(result) {
  alert(result); // 1
  return result * 2;
});

1. 프라미스 반환하기

.then(handler)에 사용된 핸들러가 프라미스를 생성하거나 반환하는 경우도있다. 이 경우 핸들러(이어지는 .then)는 프라미스가 처리될 때까지 기다렸다가 처리가 완료되면 그 결과를 받는다.

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});

예시에서 첫 번째 .then은 1을 출력하고 new Promise(…)를 반환((*))한다.
1초 후 이 프라미스가 이행되고 그 결과(resolve의 인수인 result * 2)는 두 번째 .then으로 전달된다.

두 번째 핸들러((**))는 2를 출력하고 동일한 과정이 반복된다.

따라서 얼럿 창엔 이전 예시와 동일하게 1, 2, 4가 차례대로 출력되지만, 얼럿 창 사이에 1초의 딜레이가 생깁니다.

이렇게 핸들러 안에서 프라미스를 반환하는 것도 비동기 작업 체이닝을 가능하게 해준다는것!

 

2. fetch와 체이닝 응용하기

프론트 단에서는, 네트워크 요청시 프라미스를 자주 사용한다.

let promise = fetch(url);
// 위 코드를 실행하면 url에 네트워크 요청을 보내고 프라미스를 반환한다. (fetch는 프라미스를 반환하는 함수)

위 코드를 실행하면 url에 네트워크 요청을 보내고 프라미스를 반환한다. 원격 서버가 응답을 보내면, 프라미스는 response 객체와 함께 이행된다.

fetch('/article/promise-chaining/user.json')
  .then(function(response) {
    return response.text();
  })
  .then(function(text) {
    // 원격에서 받아온 파일의 내용
    alert(text); // 텍스트의 내용
  });

'/article/promise-chaining/user.json'에서의 원격서버가 응답하면 .then 아래 코드가 실행된다. 첫번째 .then에서는 받아온 데이터의 전체 내용을 읽는 메서드인 response.text()의 결과값을 반환한다. 그럼 두번째 .then에서는 데이터의 전체 내용이 text라는 파라미터로 들어가고 alert창에 출력된다.