[JS] async await 그다음 배우는게 Promise ?

cgoing·2023년 10월 30일
16
post-thumbnail
post-custom-banner

소개😂

javascript 의 비동기 관해 배울때 callback -> Promise -> async await 순서로 알려주는 로드가 제법 많은데요?

주위 JS 개발자 주니어들을 보면, 오히려 async await 을 먼저 학습하고 익숙해지고 나서 Promise를 재대로 이해 하기 시작하는 케이스를 제법 많이 보게 됩니다.

글쓴이도 java기반 백앤드 base 이기때문에 js 의 비동기,callback 라는걸 다루고 이해하기 힘들엇었음

아직 비동기통신 ( data fetch ) 할 때 만 async await 을 사용하셨다면, 제가 Promise 라는게 얼마나 멋있는 Class 인지, async await 을 더 다양하게 사용하는 방법을 전달 하려고 합니다.

해당 글은 Promise 를 최대한 쉽게 설명하기 위해 Promise 의 목적 이해 를 토대로 작성 됐습니다.

원본글 블로그


어떤 것 을 await 할 수 있는가?🤔

Promise 를 재대로 이해 하기전에, 우리가 통신을 하기 위해 굉장히 많이 사용한 키워드

async await 키워드는 어떤 것에 사용 할 수 있을까요?

Promise Class 에만 사용 할 수 있습니다. 아니, Promise 에만 효과를 얻습니다.

예를 들어 보겠습니다.

sum(1,2) 에는 await 을 할 수 있을까요?

const sum = (a,b) => a+b
const testFunction = async ()=>{
          await sum()
}

sum 은 동기적인 함수 입니다. await 을 하게되면 별다른 효과가 없을 뿐, 런타임에러를 발생시키진 않습니다.

그렇다면 비동기함수라고 알고 있는 setTimeout 은 효과가 있을까요?


const testFunction = async ()=>{

              console.log(1);

              await setTimeout( ()=>{console.log(2)}, 3000 ) 
  
              console.log(3);

}

실행 결과 출력 순서는 1 3 2 로 될 것 입니다.

await 키워드를 사용했을때 정말로 await(기다릴수있는) 하는 것은
비동기 라기 보단, 정확히 Promise 객채 인 경우 입니다.

결과적으로 우리가 지금까지 사용했던 await 이 붙은 함수들은 전부 Promise 를 retrun 하는 함수 인 것 입니다.
ex : fetch(), axios(), databaseConnected(), async function 등등

또한 전혀 비동기 적인 내용은 없지만 함수에 async 키워드를 사용하는 순간, Promise 를 리턴하는 함수가 됩니다.

const testFunction = async ()=>{
      console.log('hello');
}

console.log(testFunction()) // Promise {<fulfilled>: undefined}

Promise 의 목적

Promise,async await 의 목적은 비동기 적 인것을 동기적으로 컨트롤 할수 있게 해주는 것 입니다.

비동기 적인 코드를 동기적으로 컨트롤한다? 🤔

코드는 한줄 한줄 순차적으로 실행 됩니다. 아래 코드는 동기적 (순차적?) 인 코드 입니다.

const testFunction = ()=>{
    console.log(1);
    console.log(2);
    console.log(3);
}

testFunction(); // 1,2,3 순으로 출력 됨. 

하지만 아래 코드는 어떨까요?

const testFunction = ()=>{
    console.log(1);
    
    document.getElementById('#btn').addEventListeners('click',()=> console.log(2) )

    console.log(3);
}

testFunction(); 

당연히 1에 이어서 3이 출력되고, 언젠간 ? 혹은 누르지 않을 수도 있는 버튼 을 클릭했을때 2가 출력 됩니다.

만약, 위 함수에서 1 2 3 순으로 출력 되기를 기대 한다면 이 함수는 어찌보면, '비동기 적이다' 라고 도 생각 할 수 도 있을 것 같아요.

위 함수를 동기적으로 만들어 줄 수 있는게 Promise 객채 입니다.

const testFunction = async ()=>{
    console.log(1);
    
    await 버튼을누를때까지기다리기();

    console.log(2);

    console.log(3);
}

testFunction(); 

버튼을누를때까지기다리기() 어떻게 구현 할수 있을까요?

Promise 는 생성자에 인자로 resolve와 reject 라는 두개의 매개변수 함수를 제공 합니다.

reject 에 대한 설명은 빼고 작성하겠습니다. resolve를 이해했다면 별거 아닌 거니깐요

말이 조금 어려운데요 Promise( 약속 )를 생성할때 resolve( 완료 ) 라는 것을 제공 받는데

resolve 는 약속이 '해결됐다' 라고 약속의 상태를 대기중 -> 완료 로 변경하는 함수 라고 생각하시면 됩니다.

// Promise에 대해 배울때 많이 나오는 예제

const promise = new Promise((resolve)=>{ // new Promise => 약속을 생성함 
		setTimeout(()=>{
			resolve() // 5초 뒤에  이 약속은 대기중인 상태에서  완료 됨  상태로 변경
		},5000)
	})

즉 어떠한 약속(new Promise)을 생성하고, 내가 원하는 시점에서 '완료'( resolve() ) 라는 상태변경을 직접 컨트롤 할수 있게됩니다.

그리고 await 이라는 키워드를 통해서 Promise(약속) 이 resolve(완료) 될때 까지 기다릴수 있게 됩니다.




const testFunction = async ()=> {
    console.log(1);

    await new Promise((resolve)=>{ // 약속 생성 
		
			document.getElementById('btn').addEventListeder('click',()=>{

				 console.log(2);

				 resolve();  // 버튼을 클릭 했을때 약속이 완료됨 
			},{once:true}) )
	})


    console.log(3);
}

그리고 resolve(1); 이렇게 약속완료 함수에 값을 넣게 되면 그 값을 뱉게 됩니다.

결국 우리가 자주 사용하던 fetch axios 같은 함수들은 아래 코드 처럼 생겼을 것 이라고 추측 할 수 있습니다.


// 실제는 XMLHttpRequest 라는 객채를 사용합니다. 아래는 추상적인 소스 입니다.

const fetch = (url,options)=>{

    const promise = new Promise( resolve =>{ // 약속 생성 
          

        const httpRequest = new httpRequest(url,options); // 서버에 요청하는 함수 생성
             
        httpRequest.addEventListeners('onResponse', response=>{ 
           // 응답이 왔을 때 ( 버튼을 클릭했을때 와 비슷하게 표현)
  

            resolve(response);  // 약속 완료 

           })

    })

  return promise;  // 이러한 약속을 리턴

}

const getProducts = async ()=>{

      const response  = await fetch('https://shop.com/products')
     
      ....
}


Promise 로 어떤것을 만들 수 있을까요? 🤔

추천드리고 싶은 것은, 프로젝트에서 공통으로 많이 사용하는 confirm() 입니다.

예를들어 확인 버튼을 눌렀을 때 resolve(true); 를 해주고, 취소 버튼을 눌렀을 때 resolve(false);

를 해주면서 아래 코드 처럼 사용 할 수 있게 만들어 보면 어떨 까요?


const deleteItem = async (id)=>{
    
    const answer = await customConfirm(' 정말 삭제할까요? ');

     if ( answer ) fetch(`/delete/${id}`); 
      ...

}
profile
사랑해
post-custom-banner

0개의 댓글