- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- sequelize
- flutter
- double quote
- nginx
- clipBehavior
- wil
- await
- RDS
- jsonwebtoken
- mongoose
- findByIdAndDelete
- JavaScript
- Node.js
- atlas
- https
- MYSQL
- Express
- Find
- css
- async
- Nodejs
- TypeScript
- moment
- til
- single quote
- mongodb
- EC2
- certbot
- TailwindCSS
- AWS
기억 휘발 방지소
자바스크립트의 async/await의 동작 이해하기 본문
async/await는 ES8에 등장한 것으로 Promise와 then보다 깔끔하게 코드를 작성할 수 있게 해준다.
👉 Promise 방식
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 2000);
});
}
promise()
.then((result) => {
console.log(result);
})
.catch((e) => {
console.error(e);
});
👉 async/await 방식
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 2000);
});
}
async function asyncFn() {
try {
const result = await promise();
console.log(result);
} catch (e) {
console.error(e);
}
}
asyncFn();
👉 Promise와 async/await 비교
- Promise에서는 catch로 에러 핸들링이 가능하지만 async/await에서는 에러 핸들링을 할 수 있는 기능이 없어서 try~catch문으로 에러 핸들링을 해야한다.
- 코드가 길어지면 길어질수록 async/await를 활용한 코드가 가독성이 좋다.
- async/await를 활용하면 비동기 코드를 동기 코드처럼 읽히게 해준다. ➡️ 코드 흐름을 이해하기 쉽다.
👉 async/await 동작 방식
await 키워드를 만나면 다음과 같이 동작한다.
- await 키워드가 붙은 대상이 함수라면 해당 함수를 실행
- 함수가 아니거나 함수의 실행이 끝나면 async 함수를 잠시 일시정지하고 콜 스택에서 마이크로 태스트 큐로 이동하며 이때, await의 위치를 기억
- 해당 함수가 콜 스택에서 나왔으니 나머지 콜 스택에 있는 함수들이 실행된다.
- 콜 스택이 모두 비워지면 이벤트 루프는 마이크로 태스트 큐에 있는 await를 만나 옮겨졌던 async 함수들을 콜 스택으로 이동시키고
- 해당 함수가 await 됐던 시점부터 다시 실행
const a = () => {
console.log("a 시작");
b();
console.log("a 끝");
};
const b = async () => {
console.log("b 시작");
await c();
console.log("b 끝");
};
const c = async () => {
console.log("c 시작");
await d();
console.log("c 끝");
};
const d = () => {
console.log("d")
};
a();
위에 코드에 대한 실행결과는 다음과 같다.
a 시작
b 시작
c 시작
d
a 끝
c 끝
b 끝
👉 동작 순서
1. a 함수가 호출/실행되어 'a 시작' 출력
Call Stack: [a]
Microtask Queue: []
콘솔 출력 결과
a 시작
2. a 함수 안에 있는 b 함수를 호출/실행되어 'b 시작' 출력
Call Stack: [a b]
Microtask Queue: []
콘솔 출력 결과
a 시작
b 시작
3. b 함수 내에서 await c(); 를 만났지만 c 함수를 호출/실행하고 콜 스택에 쌓이고 'c 시작' 출력
Call Stack: [a b c]
Microtask Queue: []
콘솔 출력 결과
a 시작
b 시작
c 시작
4. c 함수 내에서 await d();를 만났으나 d 함수를 호출/실행하고 콜 스택에 d 추가
Call Stack: [a b c d]
Microtask Queue: []
콘솔 출력 결과
a 시작
b 시작
c 시작
5. d 함수가 실행 후 종료되어 콜 스택에서 제거
Call Stack: [a b c]
Microtask Queue: []
콘솔 출력 결과
a 시작
b 시작
c 시작
d
6. await d()를 만나 일시정지된 c 함수가 콜 스택에서 마이크로 태스트 큐로 옮겨간다.
Call Stack: [a b]
Microtask Queue: [c]
콘솔 출력 결과
a 시작
b 시작
c 시작
d
7. await c()를 만나 일시정지된 b 함수가 콜 스택에서 마이크로 태스크 큐로 옮겨간다.
Call Stack: [a]
Microtask Queue: [c b]
콘솔 출력 결과
a 시작
b 시작
c 시작
d
8. 콜 스택에서 하나 남은 a 함수가 실행되어 'a 끝'이 콘솔에 출력되고 a 함수는 콜 스택에서 빠져나간다.
Call Stack: []
Microtask Queue: [c b]
콘솔 출력 결과
a 시작
b 시작
c 시작
d
a 끝
9. 콜 스택이 비었으므로 마이크로 태스트 큐에 있는 c 함수가 콜 스택으로 이동하고 await 를 만난 이후부터 실행되어 'c 끝'이 콘솔에 출력되고 콜 스택에서 제거된다.
Call Stack: []
Microtask Queue: [b]
콘솔 출력 결과
a 시작
b 시작
c 시작
d
a 끝
c 끝
10. 9번과 마찬가지로 콜 스택이 비었으므로 마이크로 태스크 큐에 있는 b 함수가 콜 스택으로 이동하고 await를 만난 이후부터 실행되어 'b 끝'이 콘솔에 출력되고 콜 스택에서 제거된다.
Call Stack: []
Microtask Queue: []
콘솔 출력 결과
a 시작
b 시작
c 시작
d
a 끝
c 끝
b 끝
async/await가 비동기 코드지만 동기처럼 보이는 이유도 await를 만난 함수를 마이크로 태스트 큐에 옮겨놓고 콜 스택이 비워졌을 때 실행하기 때문이다.
때문에 await를 만난 이후의 로직에서 await에 대한 결과값을 받을 수 있는 것이다.
혹시라도 잘못된 정보가 있다면 댓글로 알려주시면 감사하겠습니다!
참고
https://velog.io/@jjunyjjuny/JavaScript-asyncawait%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C
끝!
'Web > JavaScript' 카테고리의 다른 글
[JavaScript] shift()와 pop() (0) | 2021.10.05 |
---|---|
[JavaScript] sort() (0) | 2021.10.02 |
[JavaScript] includes() (0) | 2021.09.25 |
[JavaScript] find() (0) | 2021.09.24 |
[JavaScript] reduce() (0) | 2021.09.11 |