본문 바로가기
Front-end/Javascript

[Javascript] Callback, Promise, Async await 차이점과 사용법

by 발담그는블로그 2022. 3. 19.

Callback, Promise, Async await를 살펴보기에 앞서...

자바스크립트 엔진은 코드를 동기적으로 실행하기 때문에, 코드 중간에 엄청난 로직의 함수를 실행한다면 병목 현상이 생길 것이다. 그래서 사용하는 것이 비동기 함수다.

출처: https://elvanov.com/2597 

Callback

매개변수를 변수가 아닌 함수로 받는 함수

function callbackFun(inputFun) {
	console.log('매개변수 받는 함수');
	inputFun();
}

function inputFun(){
	console.log('매개변수 함수');
}

 

Promise

비동기 작업을 처리하는 함수

const promise1 = new Promise((resolve, reject) => {
  resolve();
});
promise1
  .then(() => {
    console.log("then!");
  })
  .catch(() => {
    console.log("catch!");
  });

- (resolve, reject) 부분은 executor 라고 부름

- new Promise(...) 하는 순간 여기에 할당된 비동기 작업이 바로 실행된다. 

- resolve: 비동기 작업 성공했어! / reject: 비동기 작업 실패했어!

- 만약에 promise 함수안에 resolve와 reject 처리를 하는 것이 없다면 계속 'pending'상태이다

- then과 catch는 promise 결과에  따라 실행되는 메소드. then: 성공했을 때 동작 지정. (인자는 함수) / catch: 실패했을 때 동작 지정. (인자는 함수)

 

 

Async

Promise를 더욱 간결하게 보이는 함수. 함수 앞에다가 async 선언만 하면 되서 쉽다.

// Promise 방법
function startAsync(age) {
  return new Promise((resolve, reject) => {
    if (age > 20) resolve(`${age} success`);    
   else reject(new Error("Something went wrong"));
  });
}

// async 방법
async function startAsync(age) {
  if (age > 20) return `${age} success`;
  else throw new Error(`${age} is not over 20`);
}

- 함수 앞에 async를 선언함

- async의 return 값은 Promise이다

- new Promise 부분을 지우고 executor 내용만 남김

- 기존 Promise의 resolve => return value 

- 기존 Promise의 reject => throw new Error

 

Await

await는 async와 같이 쓰이며, async의 return 값인 Promise가 끝날때까지 기다리는 함수다.

function setTimeoutPromise(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(), ms);
  });
}

async function startAsync(age) {
  if (age > 20) return `${age} success`;
  else throw new Error(`${age} is not over 20`);
}

async function startAsyncJobs() {
  await setTimeoutPromise(1000);
  const promise1 = startAsync(25);
  try {
    const value = await promise1;
    console.log(value);
  } catch (e) {
    console.error(e);
  }
  const promise2 = startAsync(15);
  try {
    const value = await promise2;
    console.log(value);
  } catch (e) {
    console.error(e);
  }
}

startAsyncJobs();

- await setTimeoutPromise(1000) => 1000초가 지나면 promise를 return 하는 것

 

Promise와 Async await의 차이를 더 쉬운 코드로 살펴보자면 다음과 같다.

// <예시1>
function delay(ms){
	return new Promise(resolve => setTimeout(resolve, ms));
}

// async await
async function getBanana(){
	await delay(3000);
    return 'banana';
}

// promise
function getBanana(){
	return delay(3000)
    .then(()=>'banana');
}
// <예시2>

// Promise
function pickFruits(){
	return getApple().then(apple => {
    	return getBanana().then(banana => `${apple} + ${banana}`);
    });
}

pickFruits().then(console.log);


// Async await
async function pickFruits(){
	const apple = await getApple();
    const banana = await getBanana();
    return `${apple} + ${banana}`
}

pickFruits().then(console.log);

Promise를 사용하면 성공한 뒤, 작업을 처리하는 것이기 때문에 async await를 사용하면 완벽한 비동기 처리를 할 수 있는 느낌처럼 보인다.

 

예시2의 경우 getApple, getBanana 함수는 각각 독립적인 함수기 때문에 병렬처리를 해주어야 한다. 즉, 개선을 한다면 다음과 같다.

// <예시2>
// Async await
async function pickFruits(){
	const applePromise = getApple();	//	=> 이렇게 promise를 만들면 바로 실행되기 때문 
    const bananaPromise = getBanana();
	const apple = await applePromise;
    const banana = await bananaPromise;
    return `${apple} + ${banana}`
}

pickFruits().then(console.log);

Promise를 만들고나서 병렬적으로 실행하는 것이, 가장 빠르게 실행된다.

 

Promise All

다음의 병렬처리한 메서드를 좀 더 보기 좋게 바꿔주는 api가 있는데 바로 Promise All이다.

function pickAllFruits(){
	return Promise.all([getBanana(), getApple()])
    .then(fruits => fruits.join('+'))
}

추가로 promise.ract()라는 함수를 이용하면, 병렬처리된 것 중 가장 빨리 처리된 애의 결과를 나타내준다.

 

출처: https://elvanov.com/2597, 드림코딩 엘리 (자바스크립트 13. 비동기의 꽃 JacaScript async와 await)

반응형