[Javascript] fetch와 async/await

김지원·2023년 3월 6일
0

Frontend

목록 보기
17/28

☑️fetch

Javascript에서는 fetch로 리소스를 비동기 요청을 할 수 있다. fetchPromise 객체를 리턴한다.

비동기 처리란, 시간이 소요되는 작업이 완료될 때까지 계속 기다리지 않고 따로 처리하며, 일단 다른 코드들도 먼저 실행할 수 있게끔 하는 작업이다.

이처럼 비동기 처리로 얻은 데이터를 이용해야 하는 부분이 있을 경우, 비동기 처리가 모두 완료된 뒤에 변수 등 초기화 작업을 진행하는 등 비동기 작업의 흐름을 제어해야 한다.

fetch는 아래 두 방법 모두와 같이 사용된다. 둘 다 동일한 결과를 리턴하지만, 어떻게 handle하는지가 다르다.

1) then과 함께 사용되는 promise chaining

2) async/await

async/await

💡async functions

함수 앞의 async 가 의미하는 바는 해당 함수가 항상 💡Promise 객체를 리턴한다는 것이다. 예를 들어, 아래 함수는 resolved promise with the result of 1 를 리턴한다.

async function f() {
  return 1;
}

f().then(alert); // 1

혹은 명시적으로 promise 객체를 리턴할 수 있다.

async function f() {
  return Promise.resolve(1);
}

f().then(alert); // 1

따라서, async 는 함수가 non-promise인 것들을 감싼 promise 객체를 리턴함을 보장한다.

💡await 는 뭔데?

// works only inside async functions
let value = await promise;

await는 promise가 리턴될 때 까지 기다리게 해준다.

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });

  let result = await promise; // wait until the promise resolves (*)

  alert(result); // "done!"
}

f();

함수는 (*) 라인에서 기다리는데, promise가 settle 되면 다시 함수가 실행되고 result에 리턴된 promise 가 할당된다.

즉!! await는 promise가 settle될 때까지 함수 실행을 중단한 다음 리턴된 promise 로 다시 함수를 재개한다. javascript 엔진은 그 사이에 다른 스크립트 실행, 이벤트 처리 등 다른 작업을 수행할 수 있기 때문에 CPU 리소스를 소모하지 않는다.

위는 promise.then를 사용하는 것보다 elegant한 syntax고 읽고 쓰기 좋은 코드라 할 수 있다.

💡async/await 사용한 Promise chaining Example

  1. .thenawait로 replace한다.
  2. 함수 앞에 async 를 붙여준다.
async function showAvatar() {

  // read our JSON
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // read github user
  let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
  let githubUser = await githubResponse.json();

  // show the avatar
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // wait 3 seconds
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
}

showAvatar();

💡 에러 핸들링(Error Handling)

rejection의, throw 문이 있는 것처럼 error(에러)를 발생시킨다.

async function f() {
  await Promise.reject(new Error("Whoops!"));
}

// or

async function f() {
  throw new Error("Whoops!");
}

try...catch 문으로 일반 throw와 동일한 방식으로 해당 오류를 잡을 수 있다.

async function f() {

  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    // catches errors both in fetch and response.json
    alert(err); // TypeError: failed to fetch
  }
}

f();

try...catch 가 없을 경우 .catch를 추가하여 에러 처리 가능하다.

async/awaitpromise.then/catch

async/await를 사용할 경우, .then이 거의 필요하지 않다. 왜냐하면 await가 waiting 역할을 담당해주기 때문이다. 그리고 .catch 대신 try...catch문을 사용할 수 있는데, 항상은 아니지만 보통 더 편리하다.

하지만 코드의 top level, 즉 async 함수 바깥에서는 await 구문을 사용할 수 없기 때문에 에러(error) 처리나 final result 처리를 위해 .then/catch 구문을 사용하는게 normal practice다.

async/awaitPromise.all

다수의 promise를 wait해야 할 경우, Promise.all 로 wrap한 뒤 await 를 사용할 수 있다.

// wait for the array of results
let results = await Promise.all([
  fetch(url1),
  fetch(url2),
  ...
]);

출처

profile
Make your lives Extraordinary!

0개의 댓글