게으른개발너D

Promises 1 - async and using promise 본문

개발/JavaScript

Promises 1 - async and using promise

lazyhysong 2023. 3. 30. 16:58

✨ Introduction to Async ✨

 

Promises를 시작하기 전에 JS의 비동기성과 동기성에 대해 생각해볼 필요가 있다.

 

우리는 보통 무언가를 하기 전에 생각을 한다.

요리를 하기 전에 무엇을 살지 생각하고 장을 보고 요리를 하는데, 이것들을 동시에 할 수 없다.

우리는 무언가를 먼저 해야한다.

 

멀티태스킹은 한 가지 이상의 것을 한 번에 동시에 생각하는 것이 아니다.

멀티태스킹은 단지 사이를 빠르게 스위칭 하는 것이다.

 

하지만 컴퓨터는 여러가지 일을 동시에 하고 있다.

 

Promises를 이해하려면 이런 것들을 알고 있어야한다.

왜냐면 자바스크립트는 이와 같기 때문이다. 동시에 많은 일들을 할 수 있다.

 

웹사이트에서 데이터를 어떻게 가져올까?

fetch를 이용해야한다.

const hello = fetch("https://google.com");

console.log("something");

이렇게 작성하고 콘솔창을 보면 

무언가를 가져오는데는 실패했지만, console.log로 찍은 something이라는 문자가 찍히고 난 다음 fetch가 실패했다는 메세지를 보여주고 있다.

원래라면 fetch를 먼저 하고 난 다음 something을 출력해야하는데, fetch를 하는 동안 something을 출력하고 fetch 수행 후에 실패 에러를 띄운 것이다.

이것이 자바스크립트의 비동기성이다.

자바스크립트는 프로그램의 실행을 멈추지 않는다.

 

위에서부터 아래로 실행을 하지만, fetch를 실행하자마자 한쪽에서는 어떤 action을 시작한다.

이게 비동기적 프로그램이다.

순차적으로 처리되는 게 아니라 한꺼번에 실행되는 것이다.

 

이것이 Promises의 작동 원리이다.

 

 

✨ Using Promises ✨

 

Promise를 사용하기 위해 then을 사용하는 방법을 알아 볼 것이다.

 

JS에 Promise가 끝난 이후의 명령어를 전달하려면, 언제 끝나는 건 중요하지 않고 끝나는 이후에 값을 돌려달라고 명령어를 내리는 것이다.

 

const amISexy = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, "Yes you are!");
});

amISexy.then(value => console.log(value));

then()을 적고 그 안에 값을 적어주면 된다.

이렇게 나온다!

이렇게 promise를 return  할 때는 then을 사용할 수 있다.

 

아마 대부분이 본인이 사용할 promise를 만들지는 않을 것이다.

보통 다른 사람들을 위해 promise를 만드는 작업을 하게 된다.

 

const amISexy = new Promise((resolve, reject) => {
  resolve("Yes you are!");
});

이렇게 적어주는 것도 같은 것이다.

 

이게 then을 넣어서 Promise를 사용하는 방법이다.

 

 

그리고 원한다면 function을 넣어줄 수 있다.

const amISexy = new Promise((resolve, reject) => {
  // setTimeout(resolve, 3000, "Yes you are!");
  resolve("Yes you are!");
});

const thenFn = (value) => console.log(value);

amISexy.then(thenFn);

이렇게!

 

 


만약 이 Promise에 에러가 있다면 어떻게 될까?

에러가 있다면 어떻게 보이게 될까?

 

그때가 reject를 써줘야할 차례이다.

 

promise에 에러가 생기게 되면, 우린 그걸 catch하면 된다.

const amISexy = new Promise((resolve, reject) => {
  setTimeout(reject, 3000, "Yes you ugly!");
});

3초 후에 이렇게 나오게 된다.

 

Uncaught 에러란 아무도 잡지 못한 에러라는 뜻이다.

 

그래서 에러를 (catch)잡아야 한다!

에러를 잡지 못했기때문에 console에서 이렇게 뜨는 것이다.

 

catch는 then과 비슷하지만 에러를 위해 쓰이는 것이다.

이제 이게 에러의 값을 알려 줄 것이다.

amISexy
  .then(thenFn)
  .catch(value => console.log(value));

 

이제 You are ugly!가 값으로 나올 것이다.

 

amISexy
  .then(result => console.log(result))
  .catch(error => console.log(error));

 

Promise가 resolve 되면 then이 실행된다.

그리고 Promise가 reject 되면 catch가 실행된다.

 

 

 

우리는 어떻게 Promise를 구성해야 하는지, 어떻게 하면 쓸모있게 만들 수 있는지를 알아야 한다.

then이 실행되면 catch는 실행되지 않고, catch가 실행되면 then은 실행되지 않는다.

 

 

 

✨ Chaining Promises ✨

 

amISexy가 Promise라고 하면 resolve()를 해줄 건데, 괄호 안에 뭘 넣어주면 좋을까?

const amISexy = new Promise((resolve, reject) => {
  resolve(2);
});

amISexy.then(number => console.log(number));

이렇게 하면 콘솔창에는 2라는 값이 나온다.

 

만약 console.log 대신 다른 promise를 만들어주면 어떤 결과가 나올까?

가끔 하나의 promise가 아닌 여러개를 사용해야 하는 경우도 있기 때문이다.

결과값이 여러개가 나와야 하는 경우에 말이다.

예를 들어서 API로 data를 받는다고 하자.

data를 then으로 받고나서 data가 암호로 되어있다고 가정한다면, 암호화된 부분을 풀어줘야될 것이다.

암호화를 푸는 과정에 시간이 조금 걸릴 것이므로 그 부분은 두번째 then에 넣어줄 것이다.

then을 하나 더 적어줄 것인데, 암호를 푸는 순서를 적을 then을 하나 더 넣어줄 것이다.

암호를 푼 data를 받을 때 파일로 저장을 해야 한다고 가정해 보자.

그럼 then을 하나 더 넣어줘야한다.

 

이렇게 then은 원하는 만큼, 필요한 만큼 넣을 수 있다.

 

왜냐면 모든 then은 서로의 순서가 끝나기를 기다리고 있기 때문이다.

JS를 계속 배우다 보면 이렇게 하는 과정이 필요한 순간이 올 것이다.

시간이 조금 걸리는 단계를 만들어 줄 때, then을 써주면 좋다.

이렇게 하는 과정을 chaining이라고 한다. 

const amISexy = new Promise((resolve, reject) => {
  resolve(2);
});

amISexy
  .then(number => console.log(number * 2))
  .then(otherNumber => console.log(otherNumber * 2));

 

 

promise로 resolve하는 값은 잘 나왔는데, 그 다음 then에서는 값이 넘어오지 않는다.

이렇게 된다는 건 then이 제대로 작동하지 않는다는 뜻이다.

 

Promise들을 제대로 엮고싶다면 기존의 then에서 return 값이 있어야 한다.

 

amISexy
  .then((number) => {
    console.log(number * 2);
    return number * 2;
  })
  .then((otherNumber) => {
    console.log(otherNumber * 2);
  });

이제 제대로 나온다.

 


여러개의 chain 중에서 하나에 error가 나온다면 그걸 catch 해줄 수 있다.

arrow function 을 사용하면 바로 return을 해줄 수 있다.

const timesTwo = (number) => number * 2;

amISexy
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(lastNumber => console.log(lastNumber));

 

 

중간에 에러를 추가해 보자.

amISexy
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(() => {
    throw Error("Something is Wrong!")
  })
  .then(lastNumber => console.log(lastNumber));

프로세스가 끝까지 가지 않고 중간에 에러를 낸다.

 

에러가 어떤건지 찾아낼 수도 있다.

amISexy
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(timesTwo)
  .then(() => {
    throw Error("Something is Wrong!")
  })
  .then(lastNumber => console.log(lastNumber))
  .catch(error => console.log(error));

catch가 다른 모든 then과 function 안의 에러들까지 모두 잡아줄 것이다.

 

만약 amISexy Promise 안에 곧바로 reject를 넣는다면?

const amISexy = new Promise((resolve, reject) => {
  reject(2);
});

catch에서는 error를 2로 받고, 2를 console.log 할 것이다.

 

 

 

Comments