자바스크립트는 동기적으로 처리됩니다.
물론 비동기적인 처리도 가능하게 된다.
- setTimeout
- EventListenr
- ajax
- etc...
특정 코드를 사용하면 비동기적으로 처리가 ' 된 '다.
1 + 1
setTimeout(1초후 2+2)
3 + 3
실생순서는 2 => 1초 후 4 => 6
( 동기적 처리는 하나씩 하나씩 순차대로 처리하는 것 )
1+1
setTimeout(1초 후 2+2)
3+3
실행순서는 2 -> 6 -> 1초 후 4
( 비동기는 하나 처리하고 시간 걸리는 건 따로 빼두고 그 다음 것을 처리 후 시간걸리는 것을 처리하는 것 )
열차 ( 동기 ) VS 택시 ( 비동기 ) -전 이런식으로 최대한 컴퓨터와 유사한 것을 생각해서 이해 하였습니다.
Q . 왜 알아야함?
A .
브라우저는 C++이라는 어마무시한 언어로 코드가 짜여져있다.
브라우저는 실행할 자바스크립트 코드를 발견하면 Stack에 넣고 running 한다. - stack은 그냥 코드 다 집어 넣고 맨 윗줄 부터 하나하나 실행시키는 공간이라 생각하자...
그래서 그런건 브라우저가 Stack 공간에 쌓아두지 않고
잠깐 보류후(Web API등...)에서 대기 했다가 Queue로 차례 차례
집어 넣고 Stack이 텅 빈 시점에 차례차례 집어넣어 실행한다.
특징: stack이 비어있을 때 '만' 코드를 " 순서대로 " " 하나 씩" stack에 보내버림
특정 코드를 옮겨 보관하는 곳
- 자바스크립트가 브라우저에 의해 실행되면 반드시 대기실에 옮겨 놓는 코드가 몇 개 있음 ( 실행 오래걸리는 code들 )
Sample - Stack & Queue
stack | queue | ||
코드 1번 | <- 첫 번째 실행 | Queue대기순서 : 1 Ajax요청 | <- 4번째 실행 |
코드2번 | <- 2번째 실행 | Queue대기순서 : 2 이벤트리스너 | <- 5번째 실행 |
코드3번 | <- 3번째 실행 | Queue대기순서 : 3 setTimeout | <- 6번째 실행 |
실행 순서는 " 코드1 → 코드2 → 코드3 , 그리고 Queue에 있는 4 , 5 , 6번째가 실행 예정이 었지만 " ...
그런데 stack에 코드4번이 '코드 3번까지 실행 후' 추가 되면?
stack | queue | ||
코드 4번 | <- 먼저 (첫 번째) 실행 | Queue대기순서 : 1 Ajax요청 | <- 4번째 실행 |
Queue대기순서 : 2 이벤트리스너 | <- 5번째 실행 | ||
Queue대기순서 : 3 setTimeout | <- 6번째 실행 |
코드 4번이 먼저 실행된다.
그러고 난 후 코드 5번, 코드6번이 차례로 Queue에서 Statck으로 가지만, 그런데 !!!😣 여기서 또 이벤트 리스너2가 호출되면...
브라우저에선...
stack | queue | ||
코드 5번 | <- 먼저 (첫 번째) 실행 | Queue대기순서 : 1 Ajax요청 | <- 3번째 실행 |
코드6번 | <- 두 번째 실행 | Queue대기순서 : 2 이벤트리스너 | <- 4번째 실행 |
Queue대기순서 : 3 setTimeout | <- 5번째 실행 | ||
new Queue대기순서 : 4 이벤트리스너 2 | <- 6번째 실행 |
이렇게 " 코드 5번 → 코드 6번 → Ajax요청 → 이벤트리스터 → 이벤트리스너2 실행 순서가 된다.
// 이 코드를 브라우저가 해석하면
console.log ( 1 + 1 )
setTimeout(function(){console.log(2+2)}, 3000);
console.log ( 2 + 2 )
setTimeout(function(){console.log(8+2)}, 1000);
stack | queue | ||
console.log ( 1 + 1 ) | <- 먼저 (첫 번째) 실행 | setTimeout (Web API에서 1초지나면 Queue로 보내짐); | <- 3번째 실행 |
console.log ( 2 + 2 ) | <- 두 번째 실행 | setTimeout(Web API에서 3 초지나면 Queue로 보내짐); | <- 4번째 실행 |
실행 순서는
1. console.log( 1 + 1 )
2. console.log( 2 + 2 )
3. setTimeout(function(){console.log(8+2)}, 1000); // Web API에서 1초가 지나면 Queue로 '먼저' 보내짐
4. setTimeout(function(){console.log(2+2)}, 3000); // 그다음 Web API에서 3초가 지나면 Queue로 '그 다음' 보내져 stack으로 들어가게 된다.
console.log( 1 + 1 ) // 첫 번째로 실행
setTimeout( () => console.log( 2 + 2 ) , 0 ) // 2번 째로 실행
console.log( 2 + 2 ) // 3 번째로 실행
위 코드 처럼 될까?
stack | queue | ||
console.log ( 1 + 1 ) | <- 먼저 (첫 번째) 실행 | setTimeout (Web API에서 0초지나면 Queue로 보내짐); | <- 3번째 실행 |
console.log ( 2 + 2 ) | <- 두 번째 실행 |
실행 순서는
1. console.log ( 1 + 1 )
2. console.log ( 2 + 2 )
3. setTimeout ( 0 초 )
순으로 실행된다.
- stack을 바쁘게 하지 말자
- Queue를 바쁘게 하지 말자
-> 버튼누르면(이벤트리스너) 모달창 *10000개 띄워주셈 하면 Queue에서 Stack에 올려보내는 것도 힘들고(= stack이 한가하게 맨날 비어있지 않을거임), 다른 Queue에 들어간 코드들도 실행지연이 생겨버림
code 1
code 2
code 3
code 4
.
.
.
setTimeout( () => {
for (let i = 0; i < 1e10 ; i++) {
i++
}
} , 0 )
// 참고로 setTimeout 타이머를 0초로 설정해도 실은 4ms로 동작한다고 함
//설정가능한 최소시간이 4ms 임
이렇게 공손하게 setTimeout을 이용하면 브라우저가 자바스크립트를 싹 다 훑고 마지막에 for문 식 ( = 복잡하고, 무서운 계산식 같은것 )을 계산해서 해결 가능
다른 자바스크립트 파일을 이용해서
그 파일에서 힘든 연산을 시키고 그게 완료가 되면 값을 가져오라고 명령이 가능하다.
( 이미 만들어진 Worker라는 클래스를 사용하면 됩니다. )
( 메인 js 파일 )
var myWorker = new Worker('worker.js');
w.onmessage = function(e){
console.log(e.data) //이러면 calculated계산식이 나옴
};
---------------------
(worker.js 파일)
var calculated = for (let i = 0; i < 1e10 ; i++) {
i++
} ;
postMessage( calculated ); //postMessage라는 특별한 함수가 있음
점점 코드를 만들고 수정하면서 이러 한 효율적인 코드짜기 같은 것도 눈에 밟혀 참 좋기도 하다