📌 async
: 비동기 함수를 정의, Promise를 반환
async function 함수명(매개변수) {
return 결과 값;
}
- function 앞에 async를 붙이면 해당 함수는 항상 프라미스 객체(Promise object)를 반환
- 내부에서 비동기 작업을 수행한다.
- Promise가 아닌 것은 프라미스로 감싸 반환한다. - async 함수는 항상 Promise를 반환하기 때문에 then() 메서드를 사용해서 호출, 처리⭕
async function exampleFunction() {
return "Hello, World!";
}
exampleFunction().then(result => console.log(result)); // "Hello, World!"
예시 2
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
return data;
}
fetchData().then(data => {
console.log(data); // fetchData() 함수가 반환한 데이터 출력
}).catch(error => { // fetchData() 함수에서 발생한 에러 출력
console.error('Error:', error);
});
📌 await
: Promise가 처리될 때까지 함수 실행을 기다리고, Promise가 해결되면 그 결과 값을 반환 + 함수 재개
await promise함수()
- async 함수 안에서만 동작❗
- Promise 처리를 기다리는 동안 엔진은 다른 일(이벤트 처리, 다른 스크립트 실행 등)을 할 수 있음
- await 기능
- result 꺼내오기
- 코드 실행 흐름 제어
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // promise가 이행될 때까지 기다림 (*)
alert(result); // "완료!"
}
f();
/* 함수를 호출하고, 함수 본문이 실행되는 도중
await에서 실행이 잠시 '중단’되었다가 프라미스가 처리되면 실행이 재개됨 */
✨ await 함수의 에러 핸들링
: Promise가 거부(reject)되면, await는 그 거부 이유를 던진다.
- Promise가 정상적으로 이행(resolve)되면, await promise는 프라미스 객체의 result에 저장된 값을 반환한다.
Promise가 거부(reject)되면, throw문처럼 에러가 던져진다.
// await 함수
async function f() {
await Promise.reject(new Error("에러 발생!"));
}
// throw문
async function f() {
throw new Error("에러 발생!");
}
- await가 던진 에러는 try..catch문를 사용해 잡을 수 있다.
async function f() {
try {
let response = await fetch('http://유효하지-않은-주소');
let user = await response.json();
} catch(err) { // fetch와 response.json에서 발행한 에러 모두를 여기서 잡습니다.
alert(err);
}
}
f();
- try..catch문이 없으면, async 함수를 호출해 만든 promise가 거부 상태(reject)가 된다.
- promise 함수에 catch() 함수를 추가하면 거부된 프라미스를 처리할 수 있다.
async function f() {
let response = await fetch('http://유효하지-않은-주소');
}
// f()는 거부 상태의 프라미스가 된다.
f().catch(alert); // TypeError: failed to fetch
async와 await를 사용한 프라미스 체이닝(Promise Chaining)
- 가독성이 좋다👍
- 비동기 로직을 다루기 쉬워짐 - 여러 비동기 작업에서 발생할 수 있는 에러를 한 곳에서 처리할 수 있다⭕
- then과 catch를 사용한 체이닝보다 더 간결하고 명확함 - async와 await를 사용한 코드는 디버깅이 더 쉽다👍
- 프라미스 체이닝의 경우, 여러 단계의 then 블록을 거치면서 에러가 발생한 위치를 추적하는 것이 어려울 수 있지만, async 함수 내에서는 디버깅이 더 직관적이다.
function firstAsyncTask() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("첫 번째 작업 완료"); // 1초 후에 "첫 번째 작업 완료" 메시지를 콘솔에 출력
resolve("첫 번째 결과"); // 프라미스를 해결(resolve)하여 "첫 번째 결과"를 반환
}, 1000);
});
}
function secondAsyncTask(previousResult) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("두 번째 작업 완료: " + previousResult);
resolve("두 번째 결과");
}, 1000);
});
}
function thirdAsyncTask(previousResult) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("세 번째 작업 완료: " + previousResult);
resolve("세 번째 결과");
}, 1000);
});
}
// async 키워드를 사용해 정의된 비동기 함수
async function asyncFunction() {
try {
// await를 통해 각 비동기 작업이 완료될 때까지 기다림
const firstResult = await firstAsyncTask(); // firstAsyncTask가 완료되면 firstResult에 "첫 번째 결과"가 저장
const secondResult = await secondAsyncTask(firstResult); // secondAsyncTask가 완료되면 secondResult에 "두 번째 결과"가 저장
const thirdResult = await thirdAsyncTask(secondResult); // thirdAsyncTask가 완료되면 thirdResult에 "세 번째 결과"가 저장
console.log("모든 작업 완료: " + thirdResult); // 모든 작업이 완료되면 "모든 작업 완료: 세 번째 결과" 메시지를 출력
} catch (error) {
console.error("에러 발생: " + error); // 에러 발생 시 에러 메시지 출력
}
}
asyncFunction();
// asyncFunction을 호출하여 비동기 작업을 시작