일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- useAppDispatch
- recoil
- 태그된 유니온
- ESlint
- CORS
- 타입 좁히기
- async/await
- 호이스팅
- 이분 검색
- 반공변성
- Jest
- Cypress
- SSR
- 공변성
- app router
- tailwind
- Promise
- 리터럴 타입
- React
- CI/CD
- autosize
- 투포인터
- 결정 알고리즘
- TS
- webpack
- 인터섹션
- 무한 스크롤
- RTK Query
- dfs
- map
Archives
- Today
- Total
짧은코딩
비동기는 동시가 아니다 본문
반응형
비동기
- 비동기는 동시에 돌아가는 것이 아니다!
- 순서의 문제이다.
동기 코드
- 동기 코드는 "위 -> 아래", "왼쪽 -> 오른쪽"으로 실행
- 따라서 예측이 쉽다
비동기 코드
- 보이는 코드대로 실행되지 않음
- 다만 정해진 순서는 있다
- 한 번 비동기는 영원한 비동기
- async/await, promise 등을 써도 동기로 만들 수 없다.
- 비동기를 동기로 바꾸려는 노력을 하지 말자
비동기 코드 분석
setTimeout(() => {
console.log("a");
}, 0);
setTimeout(() => {
console.log("b");
}, 1000);
setTimeout(() => {
console.log("c");
}, 2000);
(아래 글은 정확한 JS 스펙은 아니지만 99% 맞다, 스펙을 다 공부하려면 시간이 너무 오래 걸림)

- 호출 스택(처음)
- 우선 strict 모드가 아니면 호출 스택에 anonymous(this = window)가 들어감
- setTimeout이 순서대로 들어감
- 비동기 처리
- setTimeout은 비동기 함수라서 백그라운드, 테스크 큐, 이벤트 루프가 추가
- 어떤 함수가 비동기인지, 비동기 중에서도 promise인지는 검색해서 아는 방법밖에 없다.
- 백그라운드
- 우선 백그라운드 가상의 개념이다.
- js는 싱글 스레드라서 동시라는 개념이 없는데, 백그라운드에 들어가면 동시라는 개념이 생긴다.
- 왜냐면 백그라운드는 엔진(C++)이거나 OS이기 때문이다.
- 백그라운드에 들어가는거는 setTimeout의 타이머들, promise, ajax(네트워크) 요청, 이벤트 리스너 등이 들어감
- 비동기면 적어도 백그라운드를 한 번 거치겠구나 생각하면 됨
- 백그라운드에서 정해진 시간이 지나면 테스크 큐로 간다.
- 태스크 큐(M)
- 태스크 큐에는 정해진 시간이 지난 함수(fn)들이 들어간다.
- 큐(Queue)라서 FIFO이다.
- 이벤트 루프
- 결국 비동기도 실행하려면 호출 스택에 올라가 있어야 한다.
- 이벤트 루프가 호출 스택이 비어있으면 태스크 큐에서 하나씩 호출 스택으로 올려준다.
- 호출 스택
- 호출 스택이 비어있으면 fn(a)가 우선 호출 스택에 올라간다.
- fn(a)와 console.log가 호출 스택에 쌓이고, 이걸 모두 실행하면 또 fn(b)와 console.log가 쌓인다.
- 사진에서는 fn(b)까지만 그렸는데, fn(b)도 모두 실행되면 fn(c)가 쌓이게 된다.
태스크 큐에서 매크로와 마이크로
-마이크로(m)
- promise와 process.nextTick(노드에서 사용)만 마이크로로 들어간다.
- promise는 resolve 혹은 reject되는 순간에 마이크로(m)로 보내준다.
-매크로(M)
- 나머지는 다 매크로로 들어간다.
- 클릭 이벤트 리스너 같은 경우는 클릭이 되는 순간 태스크 큐의 매크로(M)로 보냄
-구분해 놓은 이유
- 컴퓨터에 동시란 거의 없지만, 만약에 동시에 매크로(M), 마이크로(m)로 들어가면 마이크로(m)에 들어간 것부터 호출 스택에 올린다.
- 만약에 마이크로(m)가 무한정으로 꽉 차 있으면, 매크로(M) 부분은 실행되지 않는다.
setTimeout(() => {
console.log("a");
}, 0);
setTimeout(() => {
console.log("b");
}, 1000);
setTimeout(() => {
console.log("c");
}, 2000);
Promise.resolve().then(() => {
console.log("p");
});
- 이 코드의 실행 결과는 p, a, b, c 순서로 출력된다.
- 왜냐면 Promise는 마이크로(m)에 들어가서 먼저 호출 스택에 올라가기 때문이다.
-출처
https://www.youtube.com/watch?v=0q_h594NDMU&list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3&index=12
반응형
'JS > 인간 JS엔진' 카테고리의 다른 글
async/await, Promise로 바꾸기 (1) | 2024.01.28 |
---|---|
Promise에도 동기는 있다! (0) | 2024.01.27 |
Promise, async/await (2) | 2024.01.25 |
블록 스코프와 매개변수 (0) | 2024.01.24 |
this를 분석할 수 없는 케이스 (0) | 2024.01.23 |