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
가 있다.
하지만 이것들은 단점이 있는데, 비동기 처리 패턴 중 가장 최근에 나온async
와 await
은 그 단점들을 보완한 문법이다. 이는 사용법도 간단하고 가독성도 좋은 편에 속한다.
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
해주고, reject
는 throw
에러를 날리면 된다.
async
& await
async
과 await
은 위에 서술했듯이 사용법도 간단하고 가독성도 좋다.
function
키워드 앞에 async
만 붙여주면 되고
비동기로 처리되는 부분 앞에 단순히 await
만 붙여주면 된다.
async
이 붙은 함수는 Promise
를 반환하고, Promise
가 아닌 것은 Promise
로 감싸 반환한다.
await
키워드를 만나면 Promise
가 처리(settled)될 때까지 기다린다.
이 키워드는 비동기 코드를 쓰면서 동기적으로 보이게 해준다.
await
키워드의 역할은 기다리게 하는 것인데, Promise
가 값을 반환할 때까지 기다리기 위해 비동기 함수의 실행을 일시 정지시킨다.
그리고 Promise
가 처리가 완료되어 resolve
되면 값만 따로 추출해서 반환한다.
💡 Tip!
ㅤ
await
은promise.then
보다 좀 더 세련되게Promise
의result
값을 얻을 수 있도록 해주는 문법이다.
promise.then
을통해 동기처리를 하는 것보다,await
을 사용하면 바로 동기처리도 되기에 가독성 좋고 쓰기도 쉽다.
async
과 await
으로 리팩토링하기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초마다 body
의 backgroundColor
를 변경해주는 함수이다.
이를 async
와 await
으로 리팩토링 해보겠다.
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
을 작성하지 않아도 되기에 작성하기도 편하다.
try
& catch
문을 사용하면 된다.
이는 쉽게 생각하면 Promise
의 reject
를 async
에서 구현한 것이다.
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)
}
}
🤷♂️