[JavaScript] 비동기 처리 async & await 정리

김진영·2022년 7월 25일
0

JavaScript

목록 보기
4/8
post-thumbnail

📋 비동기 처리 async & await 정리

자바스크립트는 단일 스레드 언어이다.
단일 스레드 언어라는 건, JavaScript는 최대 한 번에 한 줄의 코드만 실행한다는 뜻이다.
그렇다면 코드 중간에 5초정도 걸리는, 예를들어 데이터베이스에서 용량이 큰 이미지를 가져온다고 생각해보자. 그럼 5초동안 모든게 멈추는걸까?
물론 아니다. 밑의 코드를 보자.

console.log('Sending request to server!')
setTimeout(function () {
    console.log('Here is your data from your server')
}, 3000)
console.log('END!')

//---결과---//
//Sending request to server!
//END!
//Here is your data from your server

이처럼 setTimeout 함수가 아직 실행되지 않았어도 밑의 END!를 출력한다.

Javascript는 비동기 처리가 필수적인 언어이다.
비동기 처리는 그 결과가 언제 반환될지 알수 없기 때문에 동기식으로 처리하는 기법들이 사용된다. 대표적으로 위에 사용한 setTimeout, callback, Promise가 있다.

하지만 이것들은 단점이 있는데, 비동기 처리 패턴 중 가장 최근에 나온asyncawait은 그 단점들을 보완한 문법이다. 이는 사용법도 간단하고 가독성도 좋은 편에 속한다.

Promise

function test(arg) {
	return new Promise((resolve, reject) => {
    	if(arg === "O") resolve('Great!'); 
		else if(arg === "X") reject(new Error('Error!'));
	});
}
 
test("O").then((n) => console.log(n)); // Great!
test("X").catch((n) => console.log(n)); // Error!

async

async function test(arg){ 
    if(arg === "O") return "Great!";
	else if(arg === "X") throw "Error!";
}
 
test("O").then((n) => console.log(n)); // Great!
test("X").catch((n) => console.log(n)); // Error!

async을 지정해주면 Promise를 리턴하는 함수로 만들어준다.
return값은 자동으로 resolve해주고, rejectthrow 에러를 날리면 된다.


📌 1. async & await

asyncawait은 위에 서술했듯이 사용법도 간단하고 가독성도 좋다.

function 키워드 앞에 async만 붙여주면 되고
비동기로 처리되는 부분 앞에 단순히 await만 붙여주면 된다.
async이 붙은 함수는 Promise를 반환하고, Promise가 아닌 것은 Promise로 감싸 반환한다.

await 키워드를 만나면 Promise가 처리(settled)될 때까지 기다린다.
이 키워드는 비동기 코드를 쓰면서 동기적으로 보이게 해준다.
await 키워드의 역할은 기다리게 하는 것인데, Promise가 값을 반환할 때까지 기다리기 위해 비동기 함수의 실행을 일시 정지시킨다.

그리고 Promise가 처리가 완료되어 resolve 되면 값만 따로 추출해서 반환한다.

💡 Tip!

awaitpromise.then보다 좀 더 세련되게 Promiseresult값을 얻을 수 있도록 해주는 문법이다.
promise.then을통해 동기처리를 하는 것보다, await을 사용하면 바로 동기처리도 되기에 가독성 좋고 쓰기도 쉽다.


📌 2. asyncawait으로 리팩토링하기

Promise

const delayedColorChange = (color, delay) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            document.body.style.backgroundColor = color;
            resolve();
        }, delay)
    })
}

delayedColorChange('red', 1000)
    .then(() => delayedColorChange('orange', 1000))
    .then(() => delayedColorChange('yellow', 1000))
    .then(() => delayedColorChange('green', 1000))
    .then(() => delayedColorChange('blue', 1000))
    .then(() => delayedColorChange('indigo', 1000))

1초마다 bodybackgroundColor를 변경해주는 함수이다.
이를 asyncawait으로 리팩토링 해보겠다.

async & await

async function rainbow() {
    await delayedColorChange('red', 1000)
    await delayedColorChange('orange', 1000)
    await delayedColorChange('yellow', 1000)
    await delayedColorChange('green', 1000)
    await delayedColorChange('blue', 1000)
    delayedColorChange('indigo', 1000)
}

이렇게 같은 역할을 하는데도 훨씬 보기 쉽고 then을 작성하지 않아도 되기에 작성하기도 편하다.


📌 3. 비동기 함수의 오류 처리하기

try & catch문을 사용하면 된다.
이는 쉽게 생각하면 Promiserejectasync에서 구현한 것이다.

const fakeRequest = (url) => {
    return new Promise((resolve, reject) => {
        const delay = Math.floor(Math.random() * (4500)) + 500;
        setTimeout(() => {
            if (delay > 4000) {
                reject('Connection Timeout :(')
            } else {
                resolve(`Here is your fake data from ${url}`)
            }
        }, delay)
    })
}


async function makeTwoRequests() {
     let data1 = await fakeRequest('/page1')
     console.log(data1)
     let data2 = await fakeRequest('/page2')
     console.log(data2)
}

try 문에 오류가 될 코드를 적으면 catch 문에서는 어떻게 처리할지 정의하는 것이다. 그리고 여기서 e는 오류를 나타낸다.

async function makeTwoRequests() {
    try {
        let data1 = await fakeRequest('/page1')
        console.log(data1)
        let data2 = await fakeRequest('/page2')
        console.log(data2)
    }
    catch (e) {
        console.log('CAUGHT AN ERROR!')
        console.log('error is:', e)
    }
}

1개의 댓글

comment-user-thumbnail
2022년 7월 26일

🤷‍♂️

답글 달기