비동기 코드의 가독성을 올려주는 함수.
Promise 객체 위에 적용된다.
async
와 await
함수가 존재 합니다.
함수를 비동기 함수로 선언하는 키워드
함수 앞에 async
키워드를 사용하면 return
하지 않아도 Promise 객체가 반환된다.
/* 일반 함수 */
function hello(){
}
console.log(hello()); // undefined
/* async 키워드로 비동기 함수 선언 */
async function hello(){
// return new Promise() 를 사용하지 않아도 됨
}
console.log(hello()); // Promise { undefined }
비동기 함수 내부에 반환 값이 있으면 resolv
를 반환하고, 값이 없거나 오류를 전달하면
reject
를 반환합니다.
Throw
문을 사용해서 reject
에 전달될 에러 구문을 정의할 수 있다.
/* resolv */
const sing = async () => {
return 'asds';
}
sing().then((data) => {
console.log(data); // asds
})
/* reject */
const sing = async () => {
throw 'Error!';
return 'asds'; // throw 구문으로 인해 return이 무시된다
}
sing()
.then((data) => {
console.log(data);
})
.catch((data) => {
console.log(data) // Error!
})
/* reject - 2 */
const sing = async () => {
throw new Error('Error!'); // error 객체를 throw 구문에 전달
return 'asds'; // 무시됨
}
sing()
.then((data) => {
console.log(data);
})
Error 객체를 throw 구문에 전달하게 되면 오류난 부분과 오류를 해결한 부분을 확인 가능
비동기코드를 동기적으로 보이게 해주는 키워드.
Promise가 값을 반환할 때 까지 기다리기 위해서 비동기 함수의 실행을 일시정지합니다.
비동기 함수에서만 적용되기에 async와 한 쌍으로 사용 된다.
await를 사용하면 .then
메서드나 함수에 return
을 사용할 필요가 없어진다.
/* 배경색상을 변경하는 Promise */
const delayChangeColor = function (color, delay) {
return new Promise((resolv, reject) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
resolv();
}, delay)
})
}
/* 비동기 함수 사용 */
async function color() {
await delayChangeColor('red', 1000);
await delayChangeColor('green', 1000);
}
async function colorFinish() {
await color();
console.log('작업 완료');
}
colorFinish();
/*
동작 원리
1. colorFinish(); 함수 호출
2. 함수 내부에서 color() 함수를 호출합니다. 함수는 async 키워드로 비동기함수가 되었으며 비동기함수에서는
await 키워드를 사용해서 현재 프로미스가 완료될 때 까지, 다음 프로미스를 대기하게 만드는 역할을 수행
3. 빨간색으로 색상을 변경하는 함수의 프로미스가 완료되면, 초록색으로 변경하는 함수가 호출 됩니다.
4. 이 구문은 .then 메서드 내부에 return 함수와 동일하게 작동하며 가독성은 더욱 뛰어납니다.
5. color() 함수의 역할이 종료되면, colorFinish() 함수로 돌아와서 console.log를 출력합니다.
*/
Promise 작업이 완료되면 마지막으로 콘솔이 출력된다.
const fakeRequest = (url) => {
return new Promise((resolv, reject) => {
const delay = Math.floor(Math.random() * 4500) + 500;
setTimeout(() => {
if (delay > 4000) {
reject('연결 실패');
} else {
resolv(`${url} 주소로 연결 성공`);
}
}, delay)
})
}
async function makeTwoRequest() {
let data1 = await fakeRequest('page/1');
console.log(data1);
let data2 = await fakeRequest('page/2');
console.log(data2);
console.log('reject가 되면 안보인다.')
}
makeTwoRequest()
/*
makeTwoRequest() 함수는 fakeRequest() 함수로 부터 요청을 전달합니다.
프로미스의 결과값을 data1~2 변수에 저장하고, 작업이 완료되면 console.log를 출력합니다.
마지막 콘솔로그의 출력은 프로미스값이 resolv 인 경우에만 해당되고, reject 인 경우라면
오류 발생으로 인해 출력되지 않게 됩니다.
이를 해결하기 위해서 try.. catch 구문이 필요합니다.
*/
resolv() 인 경우에만 마지막 콘솔로그가 출력 된다.
/* try..catch 구문으로 reject 인 경우 에러 핸들링하기 */
const fakeRequest = (url) => {
return new Promise((resolv, reject) => {
const delay = Math.floor(Math.random() * 4500) + 500;
setTimeout(() => {
if (delay > 4000) {
reject('연결 실패');
} else {
resolv(`${url} 주소로 연결 성공`);
}
}, delay)
})
}
async function makeTwoRequest() {
try {
let data1 = await fakeRequest('page/1');
console.log(data1);
let data2 = await fakeRequest('page/2');
console.log(data2);
} catch (e) {
console.log(e);
}
console.log('reject가 되어도 보입니다.')
}
makeTwoRequest()
/*
프로미스의 결과 값이 reject가 되면 catch 구문으로 전달되어서 오류를 전달하고, 다음 코드가 실행되는데에
오류가 영향을 주지 않습니다.
*/
reject인 경우에도 에러 핸들링으로 인해서 마지막 console.log도 출력됩니다.