이제 많이 온 것 같다.. 오늘은 설탕(?) async / await 에 관해 물어보았다!
// 최신 문법 중 하나인 async await 가 너무 어려습니다. 예시와 함께 쉽게 설명해 줄 수 있으십니까?
물론입니다. async와 await는 JavaScript의 비동기 처리를 단순화하고 더 읽기 쉽게 만들기 위한 문법입니다.
async 키워드는 함수 앞에 위치하며, 이 함수는 항상 Promise를 반환하게 됩니다. 만약 함수가 명시적으로 Promise를 반환하지 않더라도, JavaScript는 암묵적으로 반환 값을 Promise로 감싸게 됩니다.
await 키워드는 async 함수 내에서만 사용할 수 있으며, Promise의 해결을 기다립니다. 즉, Promise가 이행되거나 거부될 때까지 함수의 실행을 일시 중지합니다. Promise가 이행되면 결과를 반환하고, 거부되면 예외를 발생시킵니다.
간단한 예제로 fetch()를 사용하는 async/await 함수를 살펴봅시다:
async function fetchUser() {
try {
const response = await fetch('https://api.github.com/users/github');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
fetchUser();
위 코드에서 fetchUser는 async 함수입니다.
fetch() 함수를 호출하면 Promise가 반환되는데, 이 Promise의 해결을 await 키워드를 사용하여 기다립니다.
fetch()의 Promise가 이행되면, response 변수에 이행 값이 할당됩니다.
이후에도 response.json()을 호출하여 반환되는 Promise를 기다립니다.
만약 fetch() 또는 response.json()이 오류를 발생시키면, await 표현식은 예외를 발생시킵니다.
이 예외는 try/catch 블록을 사용하여 잡을 수 있습니다.
이렇게 하면 Promise의 reject 상태에 대한 처리도 가능합니다.
// try { } catch { } 는 일단 다음시간에 ..
// 선생님 그렇다면 위의 경우 async 와 함께 선언된 fetchUser() 를 변수에 저장한다면 그것도 프로미스 객체가 나오나요?
네, 맞습니다.
async 함수는 항상 Promise를 반환하므로, fetchUser()의 반환값을 변수에 저장하면 그 변수는 Promise 객체를 참조하게 됩니다.
다음과 같이 코드를 작성하면:
let test = fetchUser();
console.log(test);
출력 결과는 Pending(대기 중) 상태의 Promise 객체가 됩니다.
이는 fetchUser() 함수가 비동기로 실행되기 때문에 즉시 반환되지 않고, 완료되기를 기다리는 중이라는 것을 의미합니다.
그런데 만약 fetchUser() 함수가 최종적으로 어떤 값을 반환한다면 (예를 들어, return data;를 추가한다면), 그 반환값은 Promise의 이행 값으로 사용되며, 이후에 then() 메소드를 사용하여 접근할 수 있습니다:
async function fetchUser() {
try {
const response = await fetch('https://api.github.com/users/github');
const data = await response.json();
return data; // 반환값 추가
} catch (error) {
console.error('Error:', error);
}
}
let test = fetchUser();
test.then(data => console.log(data)); // Promise의 이행 값에 접근
// 와우 그렇군요 신기하옵니다. 그러면 위의 코드 마지막 부분에서 let test = await fetchUser() 라고 또 await 쓸 수 있나요?
아니요, await 키워드는 async 함수 내에서만 사용할 수 있습니다.
만약 await를 async 함수 밖에서 사용하려고 시도하면, JavaScript는 SyntaxError를 발생시킵니다.
따라서, let test = await fetchUser();는 async 함수 내부에서 사용되어야 합니다.
예를 들어:
async function testFunc() {
let test = await fetchUser();
console.log(test);
}
testFunc();
위와 같이 testFunc라는 새로운 async 함수를 선언하고, 그 안에서 await fetchUser();를 호출하여 결과를 test 변수에 저장하고 출력하는 것이 가능합니다.
다만, 이렇게 함수를 정의하면 testFunc 자체도 비동기 함수가 되므로, 호출한 후에 즉시 결과를 얻지는 못하고, Promise가 이행되기를 기다려야 결과를 얻을 수 있습니다.
// 그렇다고 합니다..
// 정리 :
// 기본적으로 이렇게 async 를 붙여주면, 함수가 promise 가 된다. new Promise, resolve, reject 어쩌구 안써도 된다는 것.
async function 무슨연산(){
return 1 + 1
}
무슨연산()
.then(function(결과){
console.log('성공이옵니다' + 결과); // 성공이옵니다 2
});
// 이렇게 프로미스를 쉽게 뽑아낼수 있다
// 그렇다면 await 는 어떨까? 일단 다음과 같이 프로미스가 하나 있고, async 로 선언했을 때
async function 묶음(){
let 프로미스 = new Promise((성공, 실패)=>{
let 결과 = 1 + 1;
성공(결과);
});
}
// 프로미스 변수를 await 를 써서 처리해보자
async function 묶음(){
let 프로미스 = new Promise((성공, 실패)=>{
let 결과 = 1 + 1;
성공(결과);
});
let 프로미스반환값 = await 프로미스;
console.log(프로미스반환값);
}
묶음(); // 2
// 결과적으로 .then(콜백함수) 이걸 안쓸 수 있음..
// 그렇다면 여기서 new Promise 도 async 로 대체할 수 있을까? 가능
async function 묶음(){
async function 계산(){
let 결과 = 1 + 1;
return 결과;
}
let 프로미스반환값 = await 계산();
console.log(프로미스반환값);
}
// 근데 이건 좋은건지 나쁜건지 모르겠다.. 뭔가 더 편한 것 같기도 한데 async async 이렇게 나오니 더 헷갈리는 것도 같고
// 아무튼, 좋을 대로 쓰면 됩니다!
'javascript' 카테고리의 다른 글
[자바스크립트 29] 프로토타입과 상속 2 - 생성자함수 (0) | 2023.06.14 |
---|---|
[자바스크립트 28] 프로토타입과 상속 1 (0) | 2023.06.14 |
[자바스크립트 26] 비동기 2(프로미스) (0) | 2023.05.13 |
[자바스크립트 25] 비동기 1(콜백함수) (0) | 2023.05.13 |
[자바스크립트 24] DOM 조작 3(이벤트핸들러) (0) | 2023.05.13 |