[JavaScript] 비동기 처리 방법 (promise, async & await)

2023. 3. 19. 21:52Mobile App

https://whales.tistory.com/131 님의 글을 정리보며 내가 이해한 내용을 덧붙여보겠다!

 

동기는 요청을 보낸 후 응답을 받아야 다음 요청을 실행할 수 있다.

반면, 비동기는 요청을 보낸 후 응답과 관계없이 다음 요청을 실행한다. 따라서, 동시에 여러 작업을 처리할 수 있다.

비동기 ex) fetch, axios의 api 요청, setTimeout, 파일 읽기

 

아래는 동기/비동기의 차이를 명확히 이해할 수 있었던 이미지이다!!

출처: poiemaweb

 

 

비동기 코드를 처리하는 promise와 async & await를 알아보자.

 

promise

하나의 함수를 인자로 받고, promise가 생성되는 즉시 인자로 받아진 함수(실행자 함수라고 함)도 즉시 실행된다.

실행자 함수는 다시 2개 함수(resolve, reject) 를 인자로 받는다. 

실행자 함수가 실행되면 함수 내부에서는 비동기 작업이 이루어지고 만약 성공 시, resolve 함수 호출, 실패 시, reject 함수 호출한다.

 

* promise는 pending(대기: 미완료), fulfilled(이행), rejected(실패) 3가지 상태가 있다.

* fulfilled와 rejected 를 합쳐 settled(완료 상태)라고 한다.

// promise 객체 생성
const promise = new Promise((resolve, reject)=>{
  // resolve 또는 reject 함수가 실행됨
})

promise
.then(
	function (value){
    	// resolve가 호출되면 then이 실행(fulfilled상태)
        // value에 콜백함수 결과 값이 담김
	}
)
.catch(
	function (err){
		// reject가 호출되면 catch가 실행(rejected상태)
    	// err에 실패 사유가 담김
    }
)
.finally(
  // 콜백 작업을 마치고 무조건 실행되는 finally (생략 가능)
)

 

then 메서드는 promise의 이행, 거부 상태 모두 제어가 가능하지만 통상적으로 then에서 이행, catch에서 거부 상태를 제어한다.

아래는 then 메서드의 모두 제어 예시이다.

// promise 객체 생성
const promise = new Promise((resolve, reject)=>{
  // resolve 또는 reject 함수가 실행됨
})

promise
.then(
	function (value){
      //value에 콜백함수 결과 값이 담김
	}
	function (err){
    	// reject가 호출되면 실행(rejected상태)
    }
)
.catch(
  //reject가 호출되면 catch가 실행(rejected상태)
)
.finally(
  //콜백 작업을 마치고 무조건 실행되는 finally (생략 가능)
)

 

 

async(function) & await(keyword)

비동기식 코드를 동기식으로 표현하여 간단하게 나타내는 것이다.

promise와 달리 결과 값을 then, catch로 다루지 않고 변수에 담아 사용한다. (=> 동기적 코드처럼 작성 가능)

 

await와 async는 짝꿍이다. await는 async 함수 안에서만 동작한다.

async는 함수 앞에, await는 HTTP통신을 하는 비동기 처리 코드 앞에 붙인다.

await가 의도대로 동작하기 위해 비동기 처리 코드(axios, fetch 등 api호출 함수O)가 꼭 promise 객체를 반환해야 한다.

* promise가 아닌 것은 이행(resolved)상태의 promise로 감싸 이행된 프로미스가 반환되도록 한다.

 

const promise = function () {
  return new Promise((resolve, reject) => {
  	// 비동기 처리 코드이지만 promise를 반환하지 않기 때문에 promise의 resolve(이행)함수로 감싼 것!
    setTimeout(() => resolve("Done!!"), 2000); 
  });
};
async function asyncTest() {
  const result = await promise(); // promise가 이행될 때까지 기다렸다가,
  console.log(result); // 완료 되면 하단의 코드가 이어서 실행됨
}

asyncTest()

 

async와 await의 예외는 try, catch구문을 사용한다.

* promise에서는 .catch{}  / async&await는 catch{}

const promise = function () {
  return new Promise((resolve, reject) => {
  	// 비동기 처리 코드이지만 promise를 반환하지 않기 때문에 promise의 resolve(이행)함수로 감싼 것!
    setTimeout(() => resolve("Done!!"), 2000); 
  });
};
async function asyncTest() {
  try{
  	const result = await promise(); // promise가 이행될 때까지 기다렸다가,
  	console.log("result", result); //성공 시 result 값 출력
  }
  catch(e){
  	console.log("error", e) // 예외 시 에러 값 출력
  }
}

asyncTest()