게으른개발너D

Promises 2 - all, race, finally, fetch 본문

개발/JavaScript

Promises 2 - all, race, finally, fetch

lazyhysong 2023. 3. 30. 19:17

✨ Promise.all ✨

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

 

Promise.all() - JavaScript | MDN

Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환합니다. 주어진 프로미스 중 하나가 거부하는 경우, 첫

developer.mozilla.org

Promise.all은 주어진 모든 Promise를 실행한 후 진행되는 하나의 Promise를 반환한다.

일단 3개의 Promise들을 만들어보자.

const p1 = new Promise(resolve => {
  setTimeout(resolve, 5000, "First");
});

const p2 = new Promise(resolve => {
  setTimeout(resolve, 1000, "Second");
});

const p3 = new Promise(resolve => {
  setTimeout(resolve, 3000, "Third");
});

가끔씩 하나의 API가 아닌 3개, 4개의 API에서 값을 불러와야 할 때가 있을 것이다.

이걸 p1.then, p2.then, p3.then 이렇게 하는 것보단 promise.all을 쓰는 것이 나을 것이다.

promise.all은 한개의 promise를 리턴값으로 주는데, 모든 promise가 전부 resolve되고 나면 마지막 promise를 리턴값으로 주는 것이다.

const p1 = new Promise(resolve => {
  setTimeout(resolve, 5000, "First");
});

const p2 = new Promise(resolve => {
  setTimeout(resolve, 1000, "Second");
});

const p3 = new Promise(resolve => {
  setTimeout(resolve, 3000, "Third");
});

const motherPromise = Promise.all([p1, p2, p3]);

motherPromise.then(values => console.log(values));

5초 후에 결과가 나타나는데, 모든 promise들이 전부 진행될 때까지 기다렸다가 진행된다.

promise.all은 각각의 시간이 얼마나 걸리든지간에 전부 끝났을 때 순서에 맞춰서 값을 제공한다.

 


만약 promise가 reject되면 어떻게 될까?

resolve를 하는 대신 reject가 되게 바꿔보자

const p1 = new Promise(resolve => {
  setTimeout(resolve, 5000, "First");
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(reject, 1000, "Second");
});

const p3 = new Promise(resolve => {
  setTimeout(resolve, 3000, "Third");
});

const motherPromise = Promise.all([p1, p2, p3]);

motherPromise.then(values => console.log(values));

 

이렇게 에러가 뜬다.

 

제공한 Promise들 중 하나라도 reject되면, motherPromise도 reject된다.

motherPromise
  .then(values => console.log(values))
  .catch(error => console.log(error));

p2에 catch를 붙이지 않고 motherPromise에 catch를 이렇게 적는다면, 

p2에 적어둔 error msg가 뜬다.

이건 모든 프로세스가 제대로 작동하는 지 확인할 때 좋다.

 

 

 

✨ Promise.race ✨

 

Promise.race는 Promise.all과 사용법은 같다.

다른 점은 세개의 Promise들 중 하나라도 resolve 되거나 reject되면 된다는 것이다.

여기서 가장 빠른 게 결과를 정한다.

const p1 = new Promise(resolve => {
  setTimeout(resolve, 5000, "First");
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(reject, 1000, "I hate JS");
});

const p3 = new Promise(resolve => {
  setTimeout(resolve, 3000, "Third");
});

const motherPromise = Promise.race([p1, p2, p3]);

motherPromise
  .then(values => console.log(values))
  .catch(error => console.log(error));

Promise.race를 한다면 p2 값이 나올 것이다.

왜냐하면 p2가 가장 빠르기 때문이다.

const p1 = new Promise(resolve => {
  setTimeout(resolve, 10000, "First");
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(reject, 5000, "I hate JS");
});

const p3 = new Promise(resolve => {
  setTimeout(resolve, 3000, "Third");
});

p2의 시간을 5초로 바꾼다면?

이런 결과가 나온다.

 

 

이렇게 어느 것이 먼저 되는지 상관 없을 때 race를 사용하면 된다.

 

 

Promise.race([p1, p2, p3])
  .then(values => console.log(values))
  .catch(error => console.log(error));

motherPromise라는 변수를 만드는 것 말고 이렇게 쓰는 것도 똑같이 작동한다.

 

 

 

✨ finally ✨

 

Promise가 성공하거나 실패했을 때 우린 뭔가를 하고 싶을 것이다.

예를들어 코멘트를 API를 통해 저장하고 싶다.

그래서 유저가 save 버튼을 눌렀을 때, loading같은 spinner를 보여주고 싶다.

만약 error가 발생한다면 spinner를 멈추고 유저에게 에러를 해결하라고 보여주고 싶다,

그리고 업로드에 성공하면 spinner를 멈추고 싶다.

 

이게 바로 finally, finalizing 이다.

const p1 = new Promise(resolve => {
  setTimeout(resolve, 2000, "First");
})
  .then(value => console.log(value))
  .finally(() => console.log("I'm done!"));

 

reject로 변경해주고 catch를 추가해 보자

const p1 = new Promise((resolve, reject) => {
  setTimeout(reject, 2000, "First");
})
  .then(value => console.log(value))
  .catch(error => console.log(error))
  .finally(() => console.log("I'm done!"));

결과에 신경 쓸 것 없이, finalize 하는데 성공하든지 실패하든지 finally에 쓴 결과가 나온다.

 

로딩할 때, 하나를 얻고 두 개를 얻고 세 개를 얻고 마지막으로 데이터를 보여주거나, 로딩을 멈추거나 뭔가를 하거나 할 때, finally를 사용한다.

 

 

 

✨ Real world Promises (fetch) ✨

 

fetch를 사용해 보자!!

 

fetch는 Promise를 return 한다.

fetch가 하는 일은 뭔가를 가져오는 것이다.

fetch("https://google.com")
  .then(response => console.log(response))
  .catch(error => console.log(`X ${error}`));

성공하는 주소로 변경한다면?

fetch(`https://api.themoviedb.org/3/trending/movie/week?api_key=${MOVIE_API_KEY}`)
  .then(response => console.log(response))
  .catch(error => console.log(`X ${error}`));

이런 결과가 나온다.

 

response 말고 response.json()을 넣어보자

fetch(`https://api.themoviedb.org/3/trending/movie/week?api_key=${MOVIE_API_KEY}`)
  .then(response => console.log(response.json()))
  .catch(error => console.log(`X ${error}`));

이렇게 나오는데, response가 Promise를 리턴하는 함수를 가지고 있기 때문이다.

 

 

아래처럼 써보자.

fetch(`https://api.themoviedb.org/3/trending/movie/week?api_key=${MOVIE_API_KEY}`)
  .then(response => response.json())
  .then(potato => console.log(potato))
  .catch(error => console.log(`X ${error}`));

 

 

 

 

 

https://yts.torrentbay.to/api

 

Page not found (Error 404) - YTS YIFY

Download YIFY Movies Torrents - the only official YIFY website. Download all YTS YIFY movies torrents for free in 720p, 1080p, 4K and 3D quality. Smallest size with best quality and fast downloads at yts.torrentbay.to.

yts.torrentbay.to

JSON API를 찾아보자

fetch("https://yts.mx/api/v2/list_movies.json")
  .then(response => {
    console.log(response);
    return response.json();
  })
  .then(json => console.log(json))
  .catch(error => console.log(`X ${error}`));

이렇게 response를 얻고, response의 json 값을 아래에서 얻을 수 있다.

 

 

우린 보통 우리만의 Promise를 만들지 않아도 된다.

여기서 fetch를 쓴 것처럼 다른 사람이 만든 Promise를 사용하면 된다.

 

 

 

 

Comments