자바스크립트가 사용되는 웹은 동시에 여러개의 작업을 처리함
어떻게 처리를 하는 것일까?
위에서 보면 알 수 있듯이, 자바스크립트 엔진에는 메모리 할당을 관리하는 heap과 call stack만 존재한다. 그리고 병렬처리를 위해서는 자바스크립트 외부(WEB API / Node의 Background)를 이용하여 처리를 한다. 그리고 이러한 환경을 자바스크립트 엔진과 상호 연동하기 위하여 사용하는 것이 이벤트 루프이다.
function delay() {
for (var i = 0; i < 10000; i++);
}
function hi3() {
delay()
hi2()
console.log('hi3!') // (3)
}
function hi2() {
delay()
console.log('hi2!') // (2)
}
function hi1() {
console.log('hi1!') // (4)
}
setTimeout(hi1, 10) // (1)
hi3()
여기서 setTimeout이 얼마나 일찍 끝났건 간에, 다른 작업들이 먼저 콜 스택에 들어가 있으므로, hi1은 절대 먼저 실행되지 않는다. 그렇다면, setTimeout은 누가 다시 실행을 해줬을까?
그것은 바로 TASK QUEUE 그리고 EVENT LOOP라고 불리우는 녀석이다.
테스크 큐는 큐형태의 배열이고, 이벤트 루프는 콜 스택이 비워질 때 마다 콜백함수에서 꺼내와서 실행하는 역할을 한다.
-비동기 api들은 작업이 완료되면 콜백함수를 태스크 큐에 추가한다.
-이벤트 루프는 현재 실행중인 태스크가 없을때 태스크 큐에서 FIFO형식으로 큐를 꺼내와서 실행한다.
그렇다면 비동기 처리인 Promise.then(promise자체는 동기처리이다 .then이 있어야 비동기처리를 한다.)와 setTimeout가 같이 테스크(이벤트) 큐에 존재한다면 누구 먼저 실행이 될까?
Promise이다. Promise는 마이크로 테스크에 등록이 되어있기 때문이다. 마이크로 테스크는 일반 테스크보다 더 높은 우선 순위를 가지고 있다.
1.Callback Function
callback은 ES6에서 프로미스가 표준화 될때까지 비동기를 처리하는 공식 방법이였다.
비동기를 호출하는 함수를 호출 하면서 콜백함수라는 인자를 넣어 함수의 결과물을 필요로 하는 뒤의 로직을 구성하는 방법이다.
가독성을 위해 익명의 콜백함수들을 각각 함수로 정의해 코드 가시성을 증대 할 수 있지만, 코드의 리딩이
함수를 읽고 다음 함수를 읽는 방식으로 되지 때문에 사람에게 익숙한 명령형 사고 방식과 거리가 멀어져 생산성이 떨어짐. 이를 해결하기 위해 ES6에서 Promise가 등장
Promise의 가장 큰 특징은 비동기 상황을 하나의 객체로 표현한 것이다.
1. pending - resolve나 reject를 하지 않아 여전히 Promise 생성자 로직이 실행되는(ing) 상태
2. fulfilled - resolve가 호출되어 값을 넘길 수 있는 상태, then사용 가능상태
-> fulfilled가 되면 .then로 진행 / rejected(예외)가 되면 .catch로 진행
Promise의 병렬처리
Promise.all 메서드를 통해 병렬처리를 쉽게 다룰 수 있다.
무거운 비동기 함수들이 서로 연관이 없을 경우 병렬 처리 후 then안에 로직을 구성한다.
async await 구문은 ES8부터 적용된 비동기 처리 방식이다. 그래서 Front에서 사용하는 경우 호환성을 위해 babel의 사용이 필요
Promise의 단점은 또다른 Then 지옥을 만날 수 있다는 것이다. 그래서 이런 단점을 보완하기도 하며, 좀 더 비동기 처리를 명령형 프로그램이에 익숙하게 만들어 코드를 보기 좋게 만들 수 있다.
Async function을 선언한 후 이 함수 안에 await구문을 사용하는 방법이다.