Asynchronous Programming In Javascript - Event Loop
1] Synchronous and Asynchronous Actions

동기 처리의 경우, 함수를 호출한 후, return이 올 때 까지 기다린다. 그 후 다음 statement를 진행한다.
비동기 처리의 경우, 함수를 호출하고 return을 기다리지 않고 바로 다음 statement를 진행한다. 그 후 callback이 실행이 된다.
2] Example of Asynchronous Actions
setTimeout
HTTP requests 보내기
reading and writing data to files(파일에서 읽기와 파일에 쓰기)
DB에 query 보내기 등...
3] Event Loop in Javascript
Javascript는 위 그림과 같이 fucntion one(), two(), three(), four()를 생성하고 실행시켰을 경우, 다음과 같이 진행된다.
Global execution context을 만들고 Call stack에 넣는다.
이렇게 모든 함수를 선언하면 밑에 쓰여진 대로 one() 에 도달하게 된다.
새로운 Execution context를 Call stack의 맨 위에 생성한다.(이 Execution context는 인자, 지역변수와 함께 one()를 나타낸다.)
one()으로 들어가서, 실행하고, 끝나면 Call stack 맨 위의 execution context(새로 추가한 execution context)를 제거한다.
똑같이 two()에 도달하면, 새로운 Execution context를 생성하고, two() 안의 getNumber2()가 새로운 함수이기 때문에 또 새로운 Execution context를 생성한다.
그 후, getNumber2()가 리턴되고, EC(Execution context)가 제거되며, two()가 리턴되고, EC가 또 제거된다.
three()로 들어가서 새로운 EC를 생성하고 실행하는데, setTimeout이 비동기 함수이기 때문에, Javascript가 리턴을 기다리지 않는다. 따라서 다음으로 이동한다.
따라서 EC를 제거하고, four()로 가서 새로운 EC를 생성한다.
setTimeout이 끝났을 경우, console.log(3)을 실행하는 것이 아니라, 이 새로운 task를 Message queue(Task queue)에 추가한다. 이 task는 callback에 대한 참조가 있다.
이 callback은 Call stack이 비지 않았으므로 실행이 되지 않고, four()가 실행되고, EC를 제거한다.
끝에 도달하면, Global execution context가 Call stack에서 제거된다.
Call stack이 빌 때마다, Javascript engine은 Message queue에 뭔가 있는지 확인한다.
이 때는 1개의 task가 Message queue에 있게 되므로, Javascript engine은 Message queue에서 task를 가져와 Call stack에 새로운 EC를 생성한다.
그 후 오직 callback만을 실행하고 끝나면 EC가 call stack에서 제거된다.
그러면 Javascript가 Call stack을 체크하고, 없으면 Message queue를 다시 체크한다.
다 없으므로, Javascript engine이 종료된다.
따라서 결과는 1 2 3 4 가 아닌 1 2 4 3 이 나오게 된다.
4] Fix
four()를 three() 안에 넣어주면 된다.
function three() {
setTimeout(function () {
console.log(3);
four();
}, 0);
}