[Web-Front] Promise & Fetch

Bzeromo·2023년 10월 26일
0

HTML/CSS/JavaScript

목록 보기
5/5
post-thumbnail

⚡ Promise & Fetch


👍 이전에 포스팅했던 것도 있어용

📌 Promise

🔷 순차적인 비동기 처리하기

  • Web API로 들어오는 순서는 중요하지 않고, 어떤 이벤트가 먼저 처리되느냐가 중요. (실행 순서 불명확)

1. Async Callbacks

  • 백그라운드에서 실행을 시작할 함수를 호출할 때 인자로 지정
    ex) addEventListener() 의 두 번째 인자

2. Promise-Style

  • Modern Web APIs에서의 새로운 코드 스타일
  • XMLHttpRequest 객체를 사용하는 구조보다 조금 더 현대적인 버전

🔷 Callback

  • 함수를 매개변수로 전달하여, 나중에 실행하도록 하는 것.
  • 콜백이 중첩되면, 콜백 지옥이 되어 해석하고 유지보수하기 힘든 코드가 될 우려가 있다.(스파게티 코드)
let work = true;

function task(successCallback, failureCallback) {
  if (work) {
    successCallback();
  } else {
    failureCallback();
  }
}

function onTask1Success() {
  console.log("작업이 성공하면 이 콜백함수를 실행합니다.");
}

function onTask1Failure() {
  console.log("작업이 실패하면 이 콜백함수를 실행합니다.");
}

task(onTask1Success, onTask1Failure);

지옥이 그리 멀리 있는 것이 아니다.

🔷 Promise Object

  • 비동기 작업을 마치 동기 작업처럼 값을 반환해서 사용 형태
  • 미래의 완료 또는 실패와 그 결과 값을 나타냄.
  • 미래의 어떤 상황에 대한 약속
  • new Promise(function (resolve, reject) { })
  • resolve (성공 시 사용)
  • reject (실패 시 사용)
// Promise 생성
// Promise 생성자에 (resolve, reject) 파라미터로 하는 함수를 집어 넣음.
const p = new Promise((resolve, reject) => {
  console.log("p 작업이 수행 중입니다.");
  // 1. 작업을 수행
  let task = true;
  // 작업(성공할 수도 있고 실패할 수도 있음)을 수행
  // 시간이 오래 걸리는 작업 (비동기 작업일 수도 있음)

  // 2. 작업의 수행 결과를 결정
  // 성공 또는 실패로 끝맺음
  // resolve(msg) 함수를 호출하면 성공하고 끝남
  // reject(msg, object, array...) 함수를 호출하면 실패로 끝을 맺음
  // resolve, reject 함수의 파라미터로 결과를 전달할 수 있음.
  if (task === true) {
    resolve("p 작업이 성공했습니다.");
  } else {
    reject("p 작업이 실패했습니다.");
  }
});

// .then(): resolve된 결과가 넘어오는곳
// .catch(): reject된 결과에 대응하는 코드 작성
p.then((response) => {
  console.log(`p 프라미스가 resolve됨: ${response}`);
}).catch((response) => {
  console.log(`p 프라미스가 reject됨: ${response}`);
});

🔷 Promise Methods
1. .then(callback)

  • Promise 객체를 리턴하고 두 개의 콜백 함수를 인수로 받는다. (이행 했을 때, 거부 했을 때)
  • 콜백 함수는 이전 작업의 성공 결과를 인자로 전달 받음.

2. .catch(callback)

  • .then 이 하나라도 실패하면(거부 되면) 동작 (예외 처리 구문 유사)
  • 이전 작업의 실패로 인해 생성된 error 객체는 catch 블록 안에서 사용 가능

3. .finally(callback)

  • Promise 객체 반환
  • 결과 상관없이 무조건 실행

💡 체이닝(마치 쇠사슬 처럼 객체를 연결고리로 함수를 지속적으로 호출하는 것)이 가능하다.

// Promise 객체를 생성.
// 변수를 만드는 순간 Promise 객체가 생성됨.
// let TaskPromise = new Promise();

// => 어떤 동작을 하면서, 그동작을 할 때
// Promise 객체를 만들고 싶을 때.

// 프라미스를 함수 안에 넣기
// 함수가 프라미스를 리턴하도록 함.
function TaskPromise() {
  return new Promise((resolve, reject) => {
    console.log("Task 작업 수행 중입니다.");
    if (true) {
      resolve(("작업이 완료됐어요."));
    } else {
      reject("작업이 실패했어요");
    }
  });
}

// p.then
TaskPromise()
  .then((response) => {
    console.log(response);
  })
  .catch((response) => {
    console.log(response);
  })
  .finally(() => {
    console.log("나는 무조건 실행됩니다.");
  });

////////////////////////////////////////////////////

let task1 = false;
let task2 = false;

function task1Promise() {
  return new Promise((resolve, reject) => {
    if (task1) {
      resolve("task1이 성공했습니다.");
    } else {
      reject("task1이 실패했습니다");
    }
  });
}

function task2Promise() {
  return new Promise((resolve, reject) => {
    if (task2) {
      resolve("task2가 성공했습니다.");
    } else {
      reject("task2가 실패했습니다.");
    }
  });
}

task1Promise()
  .then((response) => {
    console.log(response);
    return task2Promise();
  })
  .then((response) => {
    console.log(response);
  })
  .catch((response) => console.log(response));

/////////////////////////////////////////////////

function TaskHasDuration(duration) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 이 작업을
      resolve(duration);
    }, duration); // duration 경과하면 수행
  });
}

// async
// 프로미스를 각각 호출하면, 비동기방식으로 코딩할 수 있다.
// TaskHasDuration(3000).then((message) => {
//   console.log(message);
// });
// TaskHasDuration(3001).then((message) => {
//   console.log(message);
// });

// sync
// 체이닝해서 동기방식으로도 사용할 수가 있다.
// TaskHasDuration(3000)
//   .then((message) => {
//     console.log(message);
//     return TaskHasDuration(3001);
//   })
//   .then((message) => {
//     console.log(message);
//   });

// Promise.all([
//   TaskHasDuration(1000), // task 1
//   TaskHasDuration(2000), // task 2
//   TaskHasDuration(3000), // task 3
//   TaskHasDuration(4000), // task 4
//   TaskHasDuration(5000), // task 5
// ]).then((messages) => {
//   // task 1, 2, 3, 4, 5에 모두 의존하는 작업을
//   // 여기서 수행
//   console.log(messages);
// });

Promise.race([
  TaskHasDuration(1000), // task 1
  TaskHasDuration(2000), // task 2
  TaskHasDuration(3000), // task 3
  TaskHasDuration(4000), // task 4
  TaskHasDuration(5000), // task 5
]).then((message) => {
  // 5개 중에 가장 빠른애 하나만!
  // 선택지가 여러개가 있을 때
  // 똑같은 기능을 하는 서버가 5개
  // 
  // task 1, 2, 3, 4, 5 중 하나만 필요한 작업을
  // 여기서 수행
  console.log(message);
});

📌 Fetch

🔷 fetch API

  • XMLHttpRequest보다 강력하고 유연한 조작이 가능
  • Promise를 지원하므로 콜백 패턴에서 자유로움
  • ES6문법은 아니고, BOM(Browser Object Model) 객체 중의 하나임.
  • fetch() 메서드를 사용함
  • fetch() 메서드는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를

🔷 fetch(resource, options) 메서드

  • resource: 리소스가 위치한 url 지정
  • options: 옵션을 지정
    • method: HTTP method
    • headers: 요청 헤더 지정
    • body: 요청 본문 지정
  • fetch 메서드는 Promise 객체를 반환

🔷 fetch() 가 반환하는 Promise 객체

  • 성공시 then() 을 이용해 처리
  • 실패시 catch()를 이용해 처리

🔷 fetch 사용 예

  • fetch 메서드는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환
  • response.text() : Response의 Body를 텍스트의 형태로 반환
  • response.json() : Response의 Body를 JSON 파싱하여 반환
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>fetch</title>
  </head>
  <body>
    <script>
      fetch("https://jsonplaceholder.typicode.com/posts/1")
        .then((response) => response.text())
        .then((text) => JSON.parse(text).body)
        .then((body) => console.log(body));
    </script>
  </body>
</html>

🔷 async & await

  • Promise 더욱 편하게 사용할 수 있는 문법
  • then 체이닝을 제거하고 비동기 코드를 동기 코드처럼 표현 하는 방법

1. async

  • function 앞에 위치
  • 항상 Promise 반환

2. await

  • await 키워드를 만나면 Promise가 처리될 때까지 기다린다.

두 번 보아야 깨닫는 것이 있음을 다시 한번 확인하는 하루...

profile
Hodie mihi, Cras tibi

0개의 댓글