NOW OR NEVER

[7주차] 5. Javascript의 Promise & async function과 await 본문

강의/제로베이스 프론트엔드 99일

[7주차] 5. Javascript의 Promise & async function과 await

LAURA 2021. 9. 19. 22:03
반응형

Javascript

Promise 프로미스

  • 자바스크립트에서 비동기를 처리하기 위해서 가장 기본이 되는 개념
  • async와 await를 배우기 위해 알아야하는 개념
  • 프로그램에서 간단한 코드가 순차적으로 한 줄 한 줄 실행된다면 어렵지 않다. 하지만 자바스크립트에서 함수를 호출했는데 그함수가 시작되고 끝나는 동안에도 프로그램은 계속 진행되어야 할 때가 많다. 이럴 때 Promise를 사용하면 비동기적 상황에서 코드를 좀 더 명확하게 표현하고 실행하도록 만들 수 있다.
  • Promise 개체 혹은 Promise 객체로 불림
  • ES6부터 자바스크립트의 표준 내장 객체로 추가됨
  • ES6를 지원하는 브라우저나 Node.js에서 전역에 있는 Promise 확인 가능

프로미스 객체 생성 방법 - 1. 생성자(new Promise)를 통해 만들기

  • new Promise(executor 함수)
  • 생성자를 통해서 프로미스 객체 만들기 가능
  • 생성자 인자로 executor 함수 사용
    • executor 함수는 resolve와 reject를 인수로 가짐
    • executor 함수 : (resolve, reject) => {함수 바디}
    • resolve와 reject는 함수
  • 생성자(new Promise(executor 함수))를 통해서 프로미스 객체를 만드는 순간 pending(대기) 상태가 됨
  • 비동기작업 많이 하는 이유 : 보통 원격의 데이터를 가져올 때 많이 사용, 원격으로 요청하고 정상적으로 받았을 때 그 받아온 데이터를 필요한 then으로 데이터를 넘겨서 주고 그것을 활용해서 어떤 ui 등을 만들다던지 그런 데에 쓰인다.

fulfilled - resolve 함수

  • executor 함수 인자 중 하나인 resolve 함수를 실행 시 fulfilled(이행 : 실행이 됐다를 알려주는 것) 상태가 됨
  • pending 상태 돌입 > 비동기적인 처리가 되는 상황 발생 > 처리가 정상적으로 끝남(비동기적인 상황이 성공적으로 완료 시) > resolve 함수 호출 > fulfilled 상태 돌입
  • 만든 프로미스 객체 사용 하기 : 프로미스 객체 지정해준 변수.then 으로 사용
  • 실무에서 사용할 땐 객체를 바로 만들어서 사용한다기보다는 실제로 사용하는 곳에서 배치를 그때 생성해서 then과 엮어주는 작업을 하게 됨
  • function에 프로미스 객체 지정 : then을 설정하는 시정을 명확하게 하고, 함수의 실행과 동시에 프로미스 객체를 만들면서 pending이 시작하도록 하기 위해 프로미스 객체를 생성하면서 리턴하는 함수를 만들어 함수 실행과 동시에 then을 설정(대규모 작업 시 유용)
  • executor의 resolve 함수를 실행할 때 인자를 넣어 실행하면, then의 callback 함수의 인자로 받을 수 있음
    • resolve(‘hello’);
      then((message) => {…})
    • then 뒤 callback에 메시지 전달 가능하고 다음 동작을 이어가는 데 필요한 결과를 전달하는 데 많이 쓰임
    • resolve의 괄호안에 객체, 문자열 등의 여러가지를 담아서 보낼 수 있다.
    • then 함수 안에서 비동기 함수를 성공한 후 데이터를 받아서 넘겨주고 싶다면 then(message => {console.log(‘내용’, message); })로 할 수 있다. 내용 뒤에 resolve의 괄호안에 있던 내용이 작성되게 됨

rejected - reject 함수

  • executor 함수 인자 중 하나인 reject 함수 실행 시 rejected(거부) 상태가 됨
  • pending 상태 돌입 > 비동기적인 처리가 되는 상황 발생 >상황이 제대로 이행되지 않고 문제 발생해서 에러 상황 발생 > reject 함수 호출 > rejected 상태로 만들기
  • 프로미스 객체가 rejected 되는 시점에 p.catch 안에 설정한 callback 함수 실행
  • executor의 reject 함수를 실행할 때 인자를 넣어 실행하면, catch의 callback 함수의 인자로 받을 수 있음
  • reject(‘error’);
    .catch((reason) => {…})
  • resolve와 같은 방식으로 사용 가능
  • 자바스크립트에는 error 객체(new Error(‘’));)가 있는 데 그 객체를 만들어서 reject에 넣어 넘기는 것이 일반적이다. error 객체 넘길 시 catch에는 reason이 아닌 error로 들어감.
  • error 객체의 상태를 담거나 error 코드를 적어서 넘겨서 처리하는 것은 앞으로 계속 작업하면서 발생할 일이다.

fulfilled / rejected 된 후 최종 실행

  • .finally( )를 설정하고, 함수를 인자로 넣음
  • .finally 괄호안에 callback 함수 지정하여 최종적으로 할 일 설정

Promise가 없었을 때 callback을 활용한 비동기 작업

  • callback의 연속
  • 비동기 작업으로 callback 작업 함
  • 보통 비동기 작업을 할 때 callback 함수를 인자로 넣어 로직이 끝나면 callback 함수를 호출한다. 이런 경우 함수가 아래로 진행되지 않고, callback 함수 안으로 중첩해 들어가면서 들여쓰기가 심한 상태로 진행된다.(callback hell)

Promise을 활용한 비동기 작업

  • then 함수에서 다시 프로미스 객체를 리턴하는 방법을 통해 체이닝하면, 비동기 작업을 순차적으로 아래로 표현할 수 있다.
    • then 함수에서 다시 프로미스 객체를 리턴하는 방법을 통하면 callback을 활용한 비동기 작업에서 들여쓰기가 안으로 들어가는 것보단(중첩) 계속 순차적으로 체이닝해서 처리가 가능하게 되서 좀 더 보기 편하다.
  • then 괄호 안에 프로미스 객체를 만들어서 return하는 형태의 함수이름만 넣어주게 되면 바로 실행

프로미스 객체 생성 방법 - 2. Promise.resolve

  • Promise.resolve(value)
  • 프로미스라는 전역개체 안에 들어있는 resolve 라는 함수를 실행하면서 프로미스 생성
  • value로 프로미스 객체를 바로 넣을 수도 있고 프로미스 객체가 아닌 일반 값을 인자로 넣어 보낼 수 있다.
    • then 메서드가 없는 프로미스 객체가 아닌 일반 값을 넣는 경우 값이 then으로 그대로 넘어와서 fulfilled 됨
  • value가 프로미스 객체인지 아닌지 알 수 없는 경우(확실하지 않은 경우) Promise.resolve로 한번 실행해서 넘기면 resolve가 되게 하거나 바로 then으로 넘어가거나 하기 때문에 그럴 때 유용하게 사용할 수 있다.
  • value가 프로미스 객체인지 아닌지 알 수 없는 경우, 사용하면 연결된 then 메서드를 실행한다.
  • value가 프로미스 객체면 resolve된 then 메서드 실행
  • value가 프로미스 객체가 아니면 value를 인자로 보내면서 then 메서드 실행
  • promise 객체가 resolve 된후 then 메서드 작성시 then 후에 그 프로미스 객체와 분리되게 됨

프로미스 객체 생성 방법 - 3. Promise.reject

  • Promise.reject를 사용하면 catch로 연결된 rejected 상태로 변경된다.
  • Promise.reject(value)
  • value 부분에는 주로 error 객체가 들어감
  • 보통 바로 프로미스로 reject를 해서 error를 생성하는 케이스는 많지는 않지만 이런 문법도 가능하다

프로미스 객체 생성 방법 - 4. Promise.all

  • Promise.all([프로미스 객체들]);
  • 프로미스 객체가 하나가 아니라 여러 개를 생성하고 프로미스 객체를 배열을 만들고 Promise.all의 인자로 넣어 실행하면 배열의 모든 프로미스 객체들이 fulfilled 되었을 때, Promise.all에 연결된 then이 그 안에 있는 callback을 부르게 된다. then 함수의 인자로 프로미스 객체들의 resolve 인자 값을 배열로 만든다음 인자값을 넣어서 Promise.all의 then에 들어있는 callback의 인자값으로 돌려주게 된다
  • 비동기 작업 여러 개를 동시에 시작해서 모든 것이 다 끝나면 뭔가 처리해줄 것이 있을 때 활용

프로미스 객체 생성 방법 - 5. Promise.race

  • Promise.race([프로미스 객체들]);
  • Promise.all과 비슷
  • Promise.all은 모든 프로미스 객체들이 fulfilled 상태가 되면 실행이 됐던 건데 Promise.race는 프로미스 객체들 중 가장 빠른 거 먼저 fulfilled 되면 그때 바로 then 함수가 실행된다.

async function와 await

  • 프로미스 기반
  • async 함수 실행 시 그 안에 있는 로직이 다 끝날 때까지 프로그램이 그냥 종료가 되지 않는다. 중간에 한 줄 한 줄 내려가면서 await가 걸려있으면 비동기적 작업이 끝날 때까지 잠시 기다렸다가 정상적으로 끝나면(resolve 되면) resolve에 넘어온 인자 값을 넘겨서 밑으로 계속 이어서 진행하게됨
  • async-await가 좋은 점 : 비동기 처리가 로직의 코드에서 밑으로 흘러가게 표현할 수 있다는 것이 가장 큰 장점이다.

async function

  • async 키워드를 function 앞에 사용하는 것
  • es 2017 표준
  • async function 함수이름() {}
  • const 함수이름 = async () => {}
  • 사용 방법 : Promise 객체를 new로 생성해서 리턴하는 형태의 함수 사용, async function 자체를 사용할 수 있는 방법(async function에서 return 되는 값은 Promise 함수로 감싸서 리턴한다)
  • async function 안에서 error를 처리한 다음 정상적인 결과를 보내고 싶다면 await 할 때 try catch로 감싸고 error에 대한 처리하고 정상적으로 밑으로 흘러서 리턴될 수 있게 한다
  • try catch 후 마지막에 finally 사용 가능(Promise에서 배운 거와 같음)
  • 정상적 동작 try-finally, 에러날 경우 catch-finally 순 동작

await

  • Promise 객체를 리턴하는 함수를 await로 호출하는 방법 : 리턴값이 ms일 경우 const ms = await 프로미스객체; 를 async function을 감싸야 함
  • await is only valid in async function : await를 쓰는 표현식이 평가되는 한 줄이 유효하려면 async function 안에서만 써야한다.
  • resolve만
  • await를 붙이면 실제로는 비동기적인 처리를 보냈지만 비동기적인 처리가 끝날 때까지 다음줄로 넘어가지 않고 기다렸다가 resolve가 되면은 resolve 될때 넣어준 인자 값을 리턴해서 그 밑으로 이어지게 됨
  • try catch
    • 비동기 처리에서 resolve와 reject를 try catch로 처리하는게 일반적으로 사용하는 형태
    • try{ } catch( ){ }로 감쌈
    • try 중괄호 안에는 정상적으로 resolve 되었을 때 출력할 것 작성
    • catch의 (error)에 rejected 되었을 때의 인자가 넘어옴

Promise와 async await 연속 처리 비교

Promise

  • 체이닝 같은 처리가 반복되면서 비동기의 로직이 이어짐
  • 계속 만들어서 리턴해서 체이닝 같은 느낌

async await

  • 한 줄 한 줄이 비동기가 끝나면 진행이 됨
  • 로직의 이동이 계속 한 줄 한 줄과 순서가 맞아들어가서 추천

Promise.all과 Promise. race 처리

  • await를 앞에 붙여 실행
  • Promise에서 설명한 것과 같이 배열로 처리됨

Tips

  • setTimeout 함수 : 특정 ms 후에 나올 함수 설정 가능
  • ms : miliseconds

7주차 후기: 프론트엔드의 꽃인 javascript 진도를 드디어 나가게 되었다. 그동안 써봤던 파이썬, C언어, JAVA와 조건문과 반복문 등 작성 방법이 비슷하면서도 아무래도 다른 언어다 보니 다른 점도 있었다. 약간 영어와 스페인어 이 둘과 같은 느낌을 받았다. 구조는 비슷한데 말하는 방식이 다른 느낌이랄까.. 아직 배우는 단계라 정확히는 모르겠지만 그래도 이해가 안되는 편은 아니였다. 얼른 기초 열심히 다져서 리액트, 뷰 까지도 배우고 싶다.

Comments