javascript async와 await

웅로그·2023년 2월 17일
0

async와 await

async와 awaits는 promise를 더욱 간결하고 동기적으로 실행되는 것처럼 만들어 준다. promise를 계속하여 체이닝하면 코드가 복잡해 지는데 이를 해결해주는 것이 async와 await이다.

async

function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다. 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다.

다음은 기존의 promise를 호출해주는 함수이다.

function fetchUser() {
	return new Promise((resolve, rejecdt) => {
    	resolve('haewoong')
   })
}

const user = fetchUser()
user.then(console.log)
console.log(user)

위 코드에 async를 써준다.

async function fetchUser() {
	return 'haewoong'
}

const user = fetchUser()
user.then(console.log)
console.log(user)

위 코드에서 fetchUser 앞에 async를 붙여주면 fetchUser 안의 코드블럭이 자동으로 promise로 바뀐다. 이로써 코드를 더 간단하게 쓸 수 있다.

await

자바스크립트는 await 키워드를 만나면 프라미스가 처리(settled)될 때까지 기다린다. 결과는 그 이후 반환한다. 여기서 프라미스는 await 키워드 뒤에 나오는 문장도 포함된다.

다음은 await를 활용하는 코드이다.

function delay(ms) {
	return new Promise(resolve => setTimeout(resolve, ms))
}

async function getApple() {
	await delay(3000)
    return '사과'
}

async function getBanana() {
	await delay(3000)
    return '바나나'
}

처음의 함수는 기존의 promise를 써줘서 시간지연 후 함수를 실행하는 문장이고 뒤의 두 함수는 async와 await를 이용해 시간지연을 준 함수이다. await 이후에 나오는 코드가 처리될때까지 기다리는 것이다.

위 코드에서 사과와 바나나를 동시에 출력해주는 함수를 작성해보자.

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

pickFruits().then(console.log)

이렇게 promise안에 promise를 부르는 체이닝을 중첩적으로 사용하게 되면 콜백지옥과 유사한 형태로 복잡해지게 된다.

위 코드를 async와 await를 사용해 간단하게 만들어 준다.

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

pickFruits().then(console.log)

병렬처리

하지만 위 코드는 문제점이 있다. getApple()과 getBanana()를 함께 실행시켜주는 것이 아니라 getApple()이 끝날때까지 기다린 다음 getBanana()가 실행되게 되어 최종적으로 6초를 기다리게 되는 것이다. 이를 해결하기 위해 '병렬처리'를 해준다.

위 코드를 개선해보자.

async function pickFruits() {
	const applePromise = getApple()
    const bananaPromise = getBanana()
	const apple = await getApple()
    const banana = await getBanana()
    return `${apple} + ${banana}`
}

pickFruits().then(console.log)

이렇게 프로미스를 따로 만들어서 getApple()과 getBanana()가 즉시 실행되게 만들어준다. 그러면 실행시간을 포함해 3초보다 약간의 시간이 더 걸리게 된다. 이 코드를 promise에서 제공하는 api를 이용해 간단히 할 수 있다.

function pickAllFruits() {
	return Promise.all([getApple(), getBanana()])
    .then(fruits => fruits.join(' + ')) //배열을 join으로 합쳐준다
}

pickAllFruits().then(console.log)

위에서 all은 promise를 병렬적으로 처리해서 결과를 배열의 형태로 모아준다.

function pickOnlyOne() {
	return Promise.race([getApple(), getBanana()])
}

pickAllFruits().then(console.log)

위의 race는 배열 안에서 가장 먼저 값을 리턴하는 promise의 결과 값만 전달하게 된다.

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

0개의 댓글