async, await
작성 수정
- Promise Chaining을 동기적인 코드인 것 처럼 만들어준다.
syntatic sugar- 코드의 가독성과 작성 편의성을 높이기 위해 제공되는 문법적 도구
- 실제 기능이나 동작에는 변함을 주지 않으면서도 기존 기능을 더 직관적이고 간결하게 사용할 수 있게 해준다.
1. async 함수
- 항상
Promise를 리턴한다.FULFILLED:async함수에서 오류 없이 끝날 경우REJECTED:async함수에서 에러가 나거나,Promise.reject()를 호출하는 경우
async function fetchUser() {
// do network request in 10secs
return 'junha';
}
const user = fetchUser(); // == Promise.resolve('junha')
console.log(user);
2. await 키워드
await는 Promise를 반환하는 표현식 앞에 사용한다. 해당 Promise가 처리(resolve)될 때까지 기다린 후 그 결과값을 반환한다.
-
await는 해당Promise가 완료될 때까지 다음 코드로 넘어가지 않게 한다.async function example() { console.log('Before'); await new Promise(resolve => setTimeout(resolve, 1000)); // Promise 객체가 생성됨 // 1초 후에 해당 Promise는 resolved 상태가 됨 console.log('After 1 second'); } -
await는 반드시async function안에서만 사용할 수 있다.async function fetchData() { const data = await fetch('https://api.example.com/data'); console.log(data); } -
Promise를 반환하는 함수 앞에await를 붙인다.async function getUser() { const user = await fetchUser(); // fetchUser()의 반환 값은 Promise 객체 console.log(user); } -
await로 받은 값은 Promise 자체가 아닌, resolved 값이다.async function getNumber() { const numberPromise = Promise.resolve(42); const number = await numberPromise; // number는 42 console.log(number); // 출력: 42 }
예시) async/await을 쓰지 않고 promise then만 쓰는 경우
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function getApple() {
return delay(2000).then(() => '🍎');
}
function getBanana() {
return delay(1000).then(() => '🍌');
}
function pickFruits() {
return getApple().then((apple) => {
return getBanana().then((banana) => `${apple} + ${banana}`);
}); // this is hard to read
}
pickFruits().then(console.log);
예시) async/await을 사용하여 동기적으로 표현한 경우
async function pickFruits() {
const apple = await getApple(); // 2초 소모
const banana = await getBanana(); // 1초 소모
return `${apple}+${banana}`; // 총 3초 소모
}
pickFruits().then(console.log);
- promise보다 간결하고 직관적으로 표현할 수 있다.
async function effPickFruits() {
const applePromise = getApple(); // execute immediately
const bananaPromise = getBanana(); // execute immediately
const apple = await applePromise; // 2초 이하 소모
const banana = await bananaPromise;
// applePromise를 기다릴 때 이미 리턴 되어있기 때문에 바로 넘어간다.
return `${apple}+${banana}`; // 총 2초 소모
}
effPickFruits().then(console.log);
3. promise 코드 => async/await 코드
Before
function displayUser(){
fetchUser()
.then((user)=>{
fetchProfile(user)//
.then((profile))=>{
updateUI(user,profile)
}
})
}
After
async function displayUser() {
const user = await fetchUser();
const profile = await fetchProfile(user);
updateUI(user, profile);
}
4. 비동기 코드를 동기처럼 작동하게 하는 예시
Before
function timer(time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(time);
}, time);
});
}
timer(1000).then(() => console.log('then 실행'));
console.log('나는 어디있을까');
// 나는 어디있을까
// (1초 후)
// then 실행
After
async function init() {
await timer(1000).then(() => console.log('then 실행'));
console.log('나는 어디있을까');
}
function timer(time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(time);
}, time);
});
}
init()
// (1초 후)
// then 실행
// 나는 어디있을까
- 비동기 코드를 동기처럼 작동하게 하는 마법은 없다,
- 동기 코드를 비동기 코드 블럭안에서 실행시켜야한다.
5. try catch in async/await
- 비동기 코드의 에러가 발생했을 경우 try-catch 구문으로 처리할 수 있다.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
// HTTP 응답 상태가 200이 아닌 경우 에러를 던짐
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log('Data:', data);
} catch (error) {
// 에러 처리
console.error('Error fetching data:', error.message);
}
}
fetchData();
await로 비동기 요청을 처리할 때 에러가 발생할 수 있다.- 이런 경우에는
try블록으로 감싸서 에러를 감지하고catch블록에서 처리한다. - 네트워크 오류나 응답 상태에 따른 예외 처리도 가능하며, 모든 종류의 에러를 잡을 수 있다.