프론트엔드 개발자 - 자곰

Front-end/Javascript

Promise(2) - 프라미스 체이닝

자곰 2023. 8. 2. 09:21

이전 포스팅에서 콜백에서 순차적으로 비동기작업을 처리할 때 콜백지옥을 보셨던 것 기억하시나요?

프로미스에선 순차적으로 처리해야하는 비동기 작업이 여러개 있을때 어떻게 해야할까요?

프라미스 체이닝을 통한 비동기 처리를 이용한다면 어렵지 않습니다.

new Promise(function(resolve, reject) {

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

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

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

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

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

}).then(function(result) {

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

});

위 예시는 아래와 같은 순서로 실행됩니다.

  1. 1초 후 최초 프라미스가 이행됩니다. – (1)
  2. 이후 첫번째 .then 핸들러가 호출됩니다. –(2)
  3. 2에서 반환한 값은 다음 .then 핸들러에 전달됩니다. – (3)
  4. 이런 과정이 계속 이어집니다.

프라미스 체이닝이 가능한 이유는 promise.then을 호출하면 프라미스가 반환되기 때문입니다. 반환된 프라미스엔 당연히 .then을 호출할 수 있습니다.

프로미스 반환하기

.then(handler)에 사용된 핸들러가 프라미스를 생성하거나 반환할수 있습니다.

new Promise(function(resolve, reject) {

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

}).then(function(result) {

  alert(result); // 1

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

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

  alert(result); // 2

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

}).then(function(result) {

  alert(result); // 4

});

예시에서 1을 출력하고 (1)를 반환합니다. 이후 1초가 지나 프라미스가 이행되고 두 번째 .then으로 전달됩니다. 이런식으로 계속되어 최종적으로 4가 출력됩니다. 아까와 다른 점은 단지 1초 딜레이가 생길 뿐입니다.

이렇게 .then은 promise를 반환하는 것이 가능합니다.

fetch와 체이닝

네트워크 요청 시 프라미스를 많이 사용하고, 데이터를 쓰기 위해 여러 체이닝이 붙는 경우가 많습니다. 이를 위한 간단한 예시를 보여드리겠습니다.

let promise = fetch(url) 가 기본적인 fetch의 문법입니다.

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

// response.json()은 원격 서버에서 불러온 내용을 JSON으로 변경해줍니다.
fetch('/article/promise-chaining/user.json')
  .then(response => response.json())
  .then(user => alert(user.name)); // Violet-Bora-Lee, 이름만 성공적으로 가져옴

정보를 이렇게 불러와서 가공할 수 있겠죠?

또 다른 예시하나 보여 드리고 마무리 하겠습니다.

이렇게 하면 과정을 분리하며 로직을 분리 시킬 수 있으니 체이닝은 잘 쓰면 좋을 것 같습니다.

fetch(~~~)
.then(response => response.json())
  .then(user => fetch(`~~~`))
  .then(response => response.json())
  .then(User => new Promise(function(resolve, reject) { // (*)
    let img = document.createElement('img');

    setTimeout(() => {
      img.remove();
      resolve(1); // (**)
    }, 3000);
  }))
    .then(res => alert(`성공적으로 실행였습니다.`));

 

 

'Front-end > Javascript' 카테고리의 다른 글

JS 스크립트  (0) 2023.08.03
Promise API  (0) 2023.08.03
Callback  (0) 2023.08.01
이벤트 위임  (0) 2023.07.28
이벤트 버블링과 이벤트 캡처링  (0) 2023.07.26