Front-end/JavaScript

JS 비동기 1편 - Promise

파리외 개발자 2023. 3. 18. 00:32

Promise

promise는 비동기에서 사용되는 연산으로,

리턴하는 프로미스 객체는

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

세 가지 형태 중 하나로 나타난다.

 

resolve, reject

const promise = new Promise((resolve, reject) => {
  if (true) {
    resolve("Worked");
  } else {
    reject("Error");
  }
});

프로미스에 성공 시 수행할 연산을 암묵적으로 resolve라 하고

실패 시 수행할 연산을 암묵적으로 reject라 한다.

promise는 성공을 하면(resolve가 실행되면)

fulfilled 상태를 리턴한다.

반대로 실패를 하면(reject가 실행되면)

rejected 상태를 리턴한다.

then

promise.then((result) => console.log(result));

then은 리턴된 프로미스 객체에 작업을 이어서 하게끔 해준다.

리턴된 fulfilled 상태의 프로미스 객체의 'Worked'는 result에 담기며

이를 콘솔에 출력한다.

promise
  .then((result) => result + "!!")
  .then((result2) => {
    console.log(result2);
  })

then은 하나 이상을 추가할 수 있다.

리턴한 데이터에 !!가 붙어서 출력된다.

 

catch

promise
  .then((result) => result + "!!")
  .then((result2) => {
    throw Error;
    console.log(result2);
  })
  .catch(() => console.log("Error"));

catch는 try catch문처럼 에러가 났을 경우 then대신 실행된다.

강제로 에러를 발생시켜서 catch를 실행시켜 본다.

promise
  .then((result) => result + "1")
  .then((result2) => result2 + "3")
  .catch(() => console.log("error"))
  .then((result3) => {
    throw Error;
    console.log(result3 + "2");
  });

catch문은 보통 맨 마지막에 작성되는데

이유는 위처럼 catch문 이후 에러가 발생한다면 잡아낼 수 없기 때문이다.

catch문이 에러를 잡아내지 못하고 있다.

 

all

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "is");
});

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

const promise4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, "isnt it?");
});

Promise.all([promise, promise2, promise3, promise4]).then((values) => {
  console.log(values);
});

새로운 프로미스를 세 개 생성한 후 setTimeout을 적용해

각각 다른 시간에 실행되게끔 한다.

all을 사용하면 여러 개의 프로미스를 한 번에 실행시킬 수 있다.

여기서 all은 제일 결과가 늦게 나오는 promise를 기다려서 

모두 실행이 끝나면 결과를 출력한다.

따라서 위 코드는 3초가 넘어서 출력을 한다.

 

fetch

const urls = [
  "https://jsonplaceholder.typicode.com/users",
  "https://jsonplaceholder.typicode.com/posts",
  "https://jsonplaceholder.typicode.com/albums",
];

fetch(urls[0]); //return Promise

promise는 보통 api통신에 쓰인다.

fetch는 url주소를 통해 데이터를 가져오며 프로미스 객체를 리턴한다.

const urls = [
  "https://jsonplaceholder.typicode.com/users",
  "https://jsonplaceholder.typicode.com/posts",
  "https://jsonplaceholder.typicode.com/albums",
];

Promise.all(
  urls.map((url) => {
    return fetch(url).then((res) => res.json());
  })
)
  .then((results) => {
    console.log(results[0]);
    console.log(results[1]);
    console.log(results[2]);
  })
  .catch((err) => console.log(err));

각 3개의 url을 all로 fetch를 하면 세 개의 결과는 콘솔에 한 번에 출력된다.