비동기

현성·2023년 12월 4일
0

동기와 비동기

  • 동기(Synchronous) : 코드가 순차적으로 실행됩니다.
  • 비동기(Asynchronous) : 코드가 순차적으로 실행되지 않습니다.

비동기 코드의 간단한 예제

console.log(1);
setTimeout(() => console.log(2), 1000);
console.log(3);

api에 요청을 보내고 1, 2, 3을 출력하고 응답이 오면 응답을 출력합니다.

fetch("https://www.omdbapi.com/?apikey=7035c60c&s=frozen")
  .then((res) => res.json())
  .then((res) => console.log(res));
console.log(1);
console.log(2);
console.log(3);

api에 요청을 보내고 응답이 오면 응답을 먼저 출력하고 1, 2, 3을 출력합니다.

fetch("https://www.omdbapi.com/?apikey=7035c60c&s=frozen")
  .then((res) => res.json())
  .then((res) => {
    console.log(res);
    console.log(1);
    console.log(2);
    console.log(3);
  });

콜백과 콜백 지옥

  • 콜백 지옥 예제
const a = (callback) => {
  setTimeout(() => {
    console.log(1);
    callback();
  }, 1000);
};

const b = (callback) => {
  setTimeout(() => {
    console.log(2);
    callback();
  }, 1000);
};

const c = (callback) => {
  setTimeout(() => {
    console.log(3);
    callback();
  }, 1000);
};

const d = () => {
  setTimeout(() => {
    console.log(4);
  }, 1000);
};

a(() => {
  b(() => {
    c(() => {
      d();
    });
  });
});
const getMovies = (movieName, callback) => {
  fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
    .then((res) => res.json())
    .then((res) => {
      console.log(res);
      callback();
    });
};

getMovies("frozen", () => {
  console.log("겨울왕국!");
  getMovies("avengers", () => {
    console.log("어벤져스!");
    getMovies("avatar", () => {
      console.log("아바타!");
    });
  });
});

Promise

  • 콜백 지옥을 해결하기 위한 클래스입니다.
const a = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(1);
      resolve();
    }, 1000);
  });
};

const b = () => console.log(2);

a().then(() => b());
const a = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(1);
      resolve();
    }, 1000);
  });
};

const b = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(2);
      resolve();
    }, 1000);
  });
};

const c = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(3);
      resolve();
    }, 1000);
  });
};

const d = () => console.log(4);

a()
  .then(() => b())
  .then(() => c())
  .then(() => d())
  .then(() => console.log("done"));

// 이렇게 작성할 수도 있습니다.
a()
  .then(b)
  .then(c)
  .then(d)
  .then(() => console.log("done"));

const getMovies = (movieName) => {
  return new Promise((resolve) => {
    fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
      .then((res) => res.json())
      .then((res) => {
        console.log(res);
        resolve();
      });
  });
};

getMovies("frozen")
  .then(() => {
    console.log("겨울왕국!");
    return getMovies("avengers");
  })
  .then(() => {
    console.log("어벤져스!");
    return getMovies("avatar");
  })
  .then(() => {
    console.log("아바타!");
  });

Async Await 패턴

const a = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(1);
      resolve();
    }, 1000);
  });
};

const b = () => console.log(2);

// a().then(() => b());

const wrap = async () => {
  await a();
  b();
};

wrap();

const getMovies = (movieName) => {
  return new Promise((resolve) => {
    fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
      .then((res) => res.json())
      .then((res) => {
        console.log(res);
        resolve();
      });
  });
};

const wrap = async () => {
  await getMovies("frozen");
  console.log("겨울왕국!");
  await getMovies("avengers");
  console.log("어벤져스!");
  await getMovies("avatar");
  console.log("아바타!");
};

wrap();

Resolve, Reject, 에러핸들링

const delayAdd = (index, cb, errorCb) => {
  setTimeout(() => {
    if (index > 10) {
      errorCb(`${index}는 10보다 클 수 없습니다.`);
      return;
    }
    console.log(index);
    cb(index + 1);
  }, 1000);
};

delayAdd(
  4,
  (res) => console.log(res),
  (err) => console.error(err)
);

  • resolvereject 사용
const delayAdd = (index) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (index > 10) {
        reject(`${index}는 10보다 클 수 없습니다.`);
        return;
      }
      console.log(index);
      resolve(index + 1);
    }, 1000);
  });
};

delayAdd(3)
  .then((res) => console.log(res))
  .catch((err) => console.error(err))
  .finally(() => console.log("Done!"));

  • async, await, try, catch 사용
const delayAdd = (index) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (index > 10) {
        reject(`${index}는 10보다 클 수 없습니다.`);
        return;
      }
      console.log(index);
      resolve(index + 1);
    }, 1000);
  });
};

const wrap = async () => {
  try {
    const res = await delayAdd(13);
    console.log(res);
  } catch (err) {
    console.error(err);
  } finally {
    console.log("Done!");
  }
};

wrap();

const getMovies = (movieName) => {
  return new Promise((resolve, reject) => {
    fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
      .then((res) => res.json())
      .then((json) => {
        if (json.Response === "False") {
          reject(json.Error);
        }
        resolve(json);
      })
      .catch((error) => {
        reject(error);
      });
  });
};

let loading = true;

// .then()
getMovies("avengers")
  .then((movies) => console.log("영화 목록:", movies))
  .catch((error) => console.log("에러 발생:", error))
  .finally(() => (loading = false));

// async / await
const wrap = async () => {
  try {
    const movies = await getMovies("avengers");
    console.log("영화 목록:", movies);
  } catch (error) {
    console.log("에러 발생:", error);
  } finally {
    loading = false;
  }
};

wrap();

반복문에서 비동기 처리

const getMovies = (movieName) => {
  return new Promise((resolve, reject) => {
    fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
      .then((res) => res.json())
      .then((res) => resolve(res));
  });
};

const titles = ["frozen", "avengers", "avatar"];

// 아래의 코드를 사용하면 frozen, avengers, avatar 순서대로 데이터를 가져올 수 없습니다.
// titles.forEach(async (title) => {
//   const movies = await getMovies(title);
//   console.log(title, movies);
// });

const wrap = async () => {
  for (const title of titles) {
    const movies = await getMovies(title);
    console.log(title, movies);
  }
};

wrap();

fetch

  • fetch(주소, 옵션)으로 사용가능합니다.
  • 네트워크를 통해 리소스의 요청(Request) 및 응답(Response)을 처리할 수 있습니다.
  • Promise 인스턴스를 반환합니다.
fetch("https://www.omdbapi.com/?apikey=7035c60c&s=avengers", {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "AA",
    age: 20,
    email: "AA@gmail.com",
  }),
})
  .then((res) => res.json())
  .then((json) => console.log(json));

const wrap = async () => {
  const res = await fetch(
    "https://www.omdbapi.com/?apikey=7035c60c&s=avengers"
  );
  const json = await res.json();
  console.log(json);
};

wrap();
profile
👈🏻 매일 꾸준히 성장하는 개발자 !

0개의 댓글