자바스크립트의 비동기 처리 패턴 중 가장 최근에 나온 문법이다.
기존의 비동기 처리 방식인 callback함수와 Promise의 단점을 보완하고, 개발자가 읽기 좋은 코드를 작성할 수 있게 도와준다!
// 일반 함수
function logName() {
var user = fetchUser('domain.com/user/1');
if(user.id === 1) {
console.log(user.name)
}
}
// 자바스크립트에서 비동기 처리 코드의 경우
// 콜백 함수 사용하면 코드의 실행 순서를 보장받을 수 있었다!
function logName() {
// 아래의 user 변수는 위의 코드와 비교하기 위해 일부러 남겨놓았습니다.
var user = fetchUser('domain.com/users/1', function(user) {
if (user.id === 1) {
console.log(user.name);
}
});
}
// async & await 추가
async function logName() {
var user = await fetchUser('domain.com/users/1');
if (user.id === 1) {
console.log(user.name);
}
}
asnyc function 함수명(){
await 비동기_처리_메서드_명();
}
fetchIteims()
함수는 프로미스 객체를 반환하는 함수이다. fetchIteims()
함수를 실행하면, 프로미스가 이행(resolved)되며, 결과 값은 items 배열이 된다.
그리고, lotItems()
함수를 실행하면 fetchItems()
함수의 결과 값인 items 배열이 resultItems 변수에 담긴다. 따라서, 콘솔에는 [1, 2, 3]
이 담긴다.
await
를 사용하지 않았다면, 데이터를 받아온 시점에 콘솔을 출력하 수 있게 콜백 함수나, then()
등을 사용해야 했을 것이다. 하지만 async await 문법을 사용함으로써 비동기에 대한 사고를 하지 않아도 되는 것이다.
function fetchItems(){
return new Promise(function(resolve, reject){
let items = [1, 2, 3];
resolve(items);
})
}
async function logItems(){
let resultItems = await fetchItems();
console.log(resultItems); // [1, 2, 3]
}
async
는 function 앞에 위치하고, async
를 붙이면 해당 함수는 항상 Promise를 반환한다.
프라미스가 아닌 값을 반환하더라도 이행(성공) 상태의 프라미스(resolved promise)로 감싸 성공한 프라미스가 반환하하고, 명시적으로 프라미스를 반환하는 것도 가능하며 결과는 동일하다.
// 프라미스 반환 (1)
async function func(){
return 1;
}
func().then(alert); // 1
// 명시적 프라미스 반환 (1)
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
await
의 대상이 되는 비동기처리코드는 Axios등 프로미스를 반환하는 API 호출 함수이다.
await
함수는 Promise가 처리될 때까지 함수 실행을 기다리도록 해준다. 즉, Promise가 성공적으로 이행되면, 그 결과와 함께 실행이 재개되는 것이다.
그리고 await
는 promise.then
보다 좀 더 깔끔하게 Promise의 result
값을 얻을 수 있도록 해주는 문법이다.
await
를 만나면, 프라미스가 처리될 때까지 기다리고, 결과를 그 이후에 반영한다.result
값이 변수 result에 할당된다. async function func(){
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('완료!'), 1000)
})
let result = await promise; // 위 Promise가 이행될 때까지 기다림 (*)
alert(result); // 완료!
}
func();
일반함수엔
await
를 사용할 수 없다!
async 함수가 아닌데, await를 사용하면 문법 에러가 발생한다.
아래 함수들을 실행하면 각각 사용자 정보와 할 일 정보가 담긴 프로미스 객체가 반환된다.
function fetchUser(){
var url = 'https://jsonplaceholder.typicode.com/users/1'
return fetch(url).then(function(response){
return response.json();
})
}
function fetchTodo(){
let url = 'https://jsonplaceholder.typicode.com/todos/1';
return fetch(url).then(function(response){
return response.json()
})
}
이 두 함수를 이용해서 할 일 제목을 출력해보자.
fetchUser()
를 이용해서 사용자 정보를 호출한다.async function logTodoTitle(){
let user = await fetchUser();
if(user.id === 1){
let todo = await fetchTodo();
console.lo(todo.title)
}
프라미스가 정상적으로 이행되면, await promise
객체의 result
에 저장된 값을 반환하지만, 프라미스가 거부되면, 마치 throw
문을 작성한 것처럼 에러가 던져진다.
async function func(){
await Promise.reject(new Error("에러 발생"));
}
// 위 코드와 동일하다.
async function func(){
throw new Error("에러 발생")
}
Promise에서 에러 처리를 위해 catch()
를 사용했던 것처럼 async에는 catch {}
를 사용하면 된다.
코드를 실행하다가 발생한 네트워크 통신 오류 뿐만 아니라, 간단한 타입 오류 등의 일반적인 오류까지도 catch
로 잡아낼 수 있다. 발견된 에러는 error
객체에 담기기 때문에 에러의 유형에 맞게 에러코드를 처리하면 된다.
async function logTodoTitle(){
try{
let user = await fetchUser();
if(user.id === 1){
let todo = await fetchTodo();
console.log(todo.title);
}
} catch(error){
console.log(error)
}
}