Promise & async await

myung hun kang·2022년 11월 10일
0

핑클 약속해줘

핑클을 아는 친구들이 있을까? 어렸을적 옥주현의 약속해줘~~~ 를 보고 "그래 옥주현은 가창력으로 아이돌하는거지~" 하고 생각했던 어린 시절이 있었다.

promise에 대해 생각하면 이 짤이 생각나곤 했는데 뭐 전혀 관련 없지만...ㅋㅋㅋㅋ

여튼 이번에는 promise를 알아보겠다!!

“A promise is an object that may produce a single value some time in the future”

Promise는 프로미스가 생성된 시점에는 알려지지 않았을 수도 있는 값을 위한 대리자로, 비동기 연산이 종료된 이후에 결과 값과 실패 사유를 처리하기 위한 처리기를 연결할 수 있습니다.

JS는 동기적인 처리만 할 수 있는 single Thread 방식의 언어이다.
즉, 비동기처리는 할 수 없다는 이야기인데

비동기처리를 가능하게 해주는 도구가 바로 promise라고 할 수 있겠다.

Promise는 비동기 연산을 처리 후 결과값을 resolve(성공)과 reject(실패) 경우로 나눠 처리할 수 있게 해준다.

-> Promise로 비동기 처리 후 then이나 catch로 성공 경우와 실패 경우의 결과값을 나눠 다룰 수 있고, 또 새로운 promise로 연결할 수도 있다.

비동기에서 동기 메서드처럼 값을 반환할 수도 있는데
단, 최종 결과가 아닌 어떤 시점에 결과를 제공하겠다는 Promise를 반환한다.

Promise는 다음 중 하나의 상태를 가진다.

대기(pending): 이행하지도, 거부하지도 않은 초기 상태.

이행(fulfilled): 연산이 성공적으로 완료됨.

거부(rejected): 연산이 실패함.

예제 코드

function doAsyncTask() {
	const promise = new Promise((resolve, reject)=> {
    	console.log("Async work")
      if(true){
        //성공경우 ()안에 값을 넣어서 보내도 된다.
      	resolve({x : 1})
      }else{
       //실패경우 ()안에 값을 넣어서 보내도 된다.
      	reject("Error")
      }
    }
  )
   return promise;
}

doAsyncTask()
  .then(()=> console.log("Task Compelete"))
  .catch((error) => console.log(error)

위 코드처럼 promise를 써서 resolve에 성공한 경우 reject에 실패한 경우를 보내주면 되는데 reject

만약 실패한 경우 실패한 이유를 error값으로 받고 싶다면 위 처럼
catch(error)로 error 값을 받아도 된다.

catch 대신 여기서 then을 또 쓰고 그안에 error를 써도 error를 다룰 수 있다.

	.then(()=>console.log("할일을 하고 "))
    .then((error) => console.log("에러처리를 then으로", error)

promise는 promise를 반환하기 때문에
이미 resolve된 값이라도 .then 체인을 쓸 수 있다.

const promise = Promise.resolve("done")	
promise.then((value)=>console.log("resolve된 이후라도 ", value))

--> 콘솔창에는 "resolve된 이후라도 done" 이 찍힐 것이다.

또는 이런 것도 된다.

function doAsync(){
    return Promise.resolve()
}
doAsync().then( () => console.log(message))
let message = "promise resloved"

이와 같은 경우 동기처리식이였으면 콘솔에는 message를 알 수 없다는 error가 떴을 것이다. 하지만
비동기 처리를 했기 때문에 다음 식은 문제 없이 message의 값을 출력할 것이다.

중요

  • promise는 기본적으로 비동기처리를 하지만 뒤에 붙는 callback 함수는 동기적으로 처리를 한다.

이점을 잘 기억해둬야 한다.

promise에는 then catch 말고도 finally 와 all도 있다.

finally

Promise가 resolve 했던 reject 했던 finally 안에 행동을 실행한다.

Promise.resolve("done")
.then(val => {
  throw "fail";
})
.catch(err => console.log(err))
.finally(()=> console.log("Cleaning UP"))

위 코드는 어떤 값을 콘솔 창에 출력할까?

프로미스가 done을 resolve하고나면 "fail"이라고 에러를 띄운다
그러므로 catch에서 error를 인식해 콘솔창에 error를 띄울텐데 그리고 끝일까?

보통의 경우 에러가 발생하면 error를 띄우고 끝난다. 하지만 이 경우 finally가 있기 때문에 에러 메세지 후에 finally의 "Cleaning UP"도 나오는 것을 확인할 수 있다. --> 어떤 경우에도 finally는 실행된다.

all

비동기처리시 데이터 fetching과 같은 작업은 굳이 작업별 순서를 정하지 않아도 된다. 외부 API에서 데이터를 가져오는 작업들이 각자 걸리는 시간이 다르므로 동시에 진행해도 무방한데 이를 가능하게 해주는게 Promise.all이다.

const doAsyncTask = (delay) => {
  return new Promise(resolve => setTimeout(() => resolve(delay),delay))
  
let promises = [doAsyncTask(1000), doAsyncTask(2000), doAsyncTask(500)]
Promise.all(promises).then(values => console.log(values))

위 코드 실행시 콘솔 창에는 몇초후에 값이 찍힐까?

만약 비동기 작업이 순차적으로 진행되었으면 총 3.5초 뒤에 값이 나왔을 것이다.

하지만 3가지 비동기 작업을 동시에 진행하게 all을 썼기 때문에 2초뒤에 값이 나오게 된다.

promise와 async await의 차이

차이 설명을 위한 코드부터 보자

const doAsyncTask = () => {
  Promise.resolve("done")
 // IIFE 로 async await 사용
(async function(){
    let value = await doAsyncTask()
    console.log(value)
    console.log(done2)
 })()

위 코드를 실행하면 어떻게 출력이 될까?

async는 함수를 비동기처리 함수로 만들어주고 await 는 비동기처리하는 값이 올때까지 기다려주는 역할을 한다.

그렇기 때문에 위 코드에서 doAsyncTask() 값을 기다려주고 밑에 있는 코드들이 실행이 되므로

done done2

가 출력되는 것을 알 수 있다.

만약에

(async function(){
    doAsyncTask().then((value) => console.log(value))
    console.log(done2)
 })()

으로 promise then 체인이었다면 출력은

done2 done

이었을 것이다.

  • await으로 값을 기다리고 다음 코드로 넘어간다는 점에서 async await 은 비동기 함수를 동기처리해준다 할 수 있다.
  • async await에서 에러 핸들링은 try().catch()로 할 수 있다.
  • async를 붙이면 그 함수가 Promise를 리턴하기 때문에 .then 을 쓸 수는 있지만 await만 쓰는 것은 안된다.


참고

Udemy Advanced Javascript -> Asim Hussain

profile
프론트엔드 개발자입니다.

0개의 댓글