async/await vs Promise

Jae·2024년 8월 20일
0

Javascript

목록 보기
1/2

먼저 비동기 작업이란 특정 코드의 로직이 끝날 때까지 기다리지 않고, 나머지 코드를 먼저 실행하는 것이다. 비동기 프로그래밍은 웹에서 메인 스레드를 차단하지 않고 시간 소모적인 작업을 병렬적으로 수행할 수 있도록 하는 중요한 기능이다.

Promise

Promise는 비동기 함수의 결과를 담고 있는 독자적인 객체이다. 비동기 작업이 끝날 때까지 결과를 기다리는 것이 아니라, 결과를 제공하겠다는 약속을 반환한다는 의미이다.
Promise 객체는 resolvereject로 나눠져서 성공과 실패 메서드로 나누어진다.
Promise 객체 내부에서 resolve를 호출하게 되면 바로 .then메서드로 이어져서 콜백함수에서 성공에 대한 추가 처리를 진행한다.
반대로 Promise객체 내부에서 reject를 호출하게 되면 바로 .catch메서드로 이어져서 추가적인 처리가 진행된다.
.finally 키워드는 프로미스가 이행되거나 거부되는 것과 상관없이 실행할 콜백함수를 등록하여 처리할 수 있다.
promise의 상태에는 진행중: pending, 성공: fulfilled, 실패: rejected가 있다.

async/await

함수 앞에 async를 붙이면 "이 함수는 비동기적인 함수이고 Promise 를 반환한다"라고 선언하는 것과 같다. async를 붙이게되면 어떤 값을 리턴하든 무조건 프로미스 객체로 감싸져 반환된다는 특징이 있습니다.
await를 붙이면, 해당 Promise의 상태가 바뀔 때까지 코드가 기다려야한다. Promise가 성공 상태 또는 실패 상태로 바뀌기 전까지는 다음 연산을 시작하지 않는 것과 같다.
async/await내부에서 Promise.resolve(fulfilled), Promise.reject(rejected)와 같이 프로미스 상태를 다르게 지정할 수 있다.

async function resolveP() {
	return Promise.resolve(2);
}
async function rejectP() {
	return Promise.reject(2);
}

async 함수 내부에서 예외 throw를 해도 실패(rejected)상태의 프로미스객체를 반환하고 return을 하지 않아도 undefined가 처리되지만 어쨌든 프로미스 객체를 반환하게 된다.

async/await vs Promise

Promise.then메서드를 연속적으로 사용하여 비동기 처리를 하지만 async/awaitawait키워드로 비동기 처리를 기다리고 있다는 것을 직관적으로 표현한다는 것을 알 수 있다. async/await비동기적 접근 방식동기적으로 작성할 수 있게 해주어 코드가 간결해지고 가독성이 높아져 유지보수를 용이하게 해준다.(단, 순서에 상관없이 데이터를 불러오는 상황에서 await를 막무가내로 사용하면 오히려 성능이 저하되는 문제가 발생한다.)

fetch('api')
	.then(response => response.json())
    .then(data => )
    .then(response => )
    .then(data => )
    .then()
    .catch()

.then메서드를 연속적으로 사용하면 코드가 길어지지고 가독성이 안좋아지지만

async function getData() {
	const response = await fetch('/api');
  	const data = await response.json();
  	const response2 = await fetch('/api2');
	...
}
getData();

위와 같이 async/await를 사용하게 된다면 훨씬 직관적이고 간결한 것을 확인할 수 있다.

Promise.then()방식의 에러 처리는 catch() 핸들러를 중간 중간에 명시함으로써 에러를 받아야하는 번거로움이 있지만 async/await와 같은 비동기 처리에 대해서 에러를 처리하려면 try/catch문을 씌우면 되게 된다.

function fetchResource(url) {
	fetch(url)
    	.then(res => res.json())
        .then(data => )
        .catch(err => );
}
async function func() {
	try {
    	const res = await fetch(url);
        const data = await res.json();
    } catch (err) {
    }
}
func();

위와 같이 async/await는 try/catch문으로 감싸면돼서 간결하고 편리하다.

await의 단점 보완(논블록킹/Promise.all)

논블록킹

데이터를 불러올 때 순서에 상관없이 데이터를 불러오는 상황이면 await를 사용하지 않고 미리 논블록킹으로 실행을 하고 난 다음에 프로미스 객체 결과 변수를 await를 통해서 꺼내쓰면 된다.

function getApple() {
	return new Promise((resolve, reject) => {
    	setTimeout(() => resolve("apple"), 1000);
	})
}
function getBanana() {
	return new Promise((resolve, reject) => {
    	setTimeout(() => resolve("banana"), 1000);
    })
}

async function getFruites() {
	console.time();
	let a = await getApple();
    let b = await getBanana();
    console.log(a, b);
    console.timeEnd();
}
getFruites();

밑에 캡쳐한 코드는 vue를 활용하여 작성한 코드이다.

위와 같이 async/await를 요청하게 된다면 a를 받은 다음에 b를 실행하기 때문에 시간이 오래걸린다. 이를 해결하기 위해서는 아래와 같이 작성해주면 된다.

async function getFruites() {
	console.time();
	let getApplePromise = getApple();
    let getBananaPromise = getBanana();
    // 위와 같이 async함수를 논블록킹으로 작성하면 백단에서 독립적으로 거의 동시에 실행되게 된다.
    let a = await getApplePromise;
    let b = await getBananaPromise;
    // 결과 변수를 await를 통해 꺼내온다.
    console.log(a, b);
    console.timeEnd();
}
getFruites();

Promise.all

Promise.all은 배열 인자의 각 프로미스 비동기 함수들이 resolved가 모두 되어야 결과를 리턴 받는다. 배열인자의 각 프로미스 함수들은 제각각 비동기 논블록킹으로 실행되어 시간을 단축할 수 있다.

async function getFruites() {
	console.time();
	let [ a, b ] = await Promise.all([getApple(), getBanana()]);
    console.log(a, b);
    console.timeEnd();
}
getFruites();

profile
즐겁게 개발

0개의 댓글

관련 채용 정보