
함수가 일정 시간이 경과 된 후에 호출되도록 예약하는 시스템, 이때 타이머함수 사용
타이머 함수는 타이머를 생성할 수 있는 setTimeout, setInterval과
제거할 수 있는 clearTimeout, clearInterval이 있습니다.
각자의 기능은 다 아실테니 넘어가겠습니다..!
타이머 함수는 ECHMAScript 사양에 정의된 빌트인 객체는 아닙니다.
그러나 호스트 객체(21.1절)로서 브라우저 환경, node.js 환경에서 모두 전역 객체의
메서드로 타이머 함수를 제공합니다.
JS 엔진은 단 하나의 실행 컨텍스트 스택을 갖기 때문에 두개 이상의 테스크를 동시에 실행할 수 없다는 특징이 있습니다. 따라서 타이머 함수는 비동기 처리 방식(42장)으로 동작합니다.
1. callback : 타이머가 만료된 후 호출할 콜백함수
2. delay: ms 단위로, 타이머의 만료시간
중요) delay의 경우, 타이머가 만료시간을 정하는 것이지, callback 함수의 호출 시점을 정해주는 것은 아님을 인지하고 있어야 합니다.
setTimeout(name=>console.log(`화이팅! ${name}`),300,'Kim');
setTimeout과 setInterval은 생성된 타이머를 식별할 고유한 타이머 id를 반환합니다.
이 반환된 타이머 id는 clearTimeout, clearInterval의 인자로 들어가며 타이머를 취소할 수 있습니다.
const timerId= setTimeout(()=>console.log(`화이팅!`),300);
...
clearTimeout(timerId);
scroll, mousemove,input, resize같이 짧은 간격으로 연속해서 발생하는 이벤트에 처리해주는 프로그래밍 기법입니다.
디바운스는 짧은 시간 간격으로 여러 이벤트가 발생할 때 이벤트 핸들러를 호출하고 있지 않다가 일정 시간(delay)이 지난 후에 이벤트 핸들러가 단 한번 호출되도록 하는 기법입니다.
const debounce= (callback,delay)=>{
let timerId;
return (...args)=>{
if(timerId) clearTimeout(timerId);
timerId= setTimeout(callback,delay,...args);
}
}
예를들어 input 이벤트가 여러번 발생했을 때 만료 시간이 지나지 않았는데 새로운 input 이벤트가 발생한다면 이전 타이머를 취소하고 새로운 타이머를 생성해 재설정합니다.
결과적으로 일정 시간이 지나야지만 callback 함수가 호출되기 때문에 여러 input 이벤트가 발생하더라도 콜백함수는 단 한번 호출되는 것입니다.
스로틀은 짧은 시간 간격으로 이벤트가 연속해서 발생해도 일정 시간을 간격으로 두어서 그 일정 시간동안 발생한 이벤트들을 하나로 그룹화하여 일정 시간 단위로 이벤트 핸들러가 한번만 호출되도록 하는 기법입니다.
const throttle= (callback,delay)=>{
let timerId;
return (...args)=>{
if(timerId) return;
timerId=setTimeout(()=>{
callback(...args);
timerId=null;
},delay);
}
}
예를들어 scroll 이벤트의 경우, delay(500ms)동안 scroll을 하더라도 delay가 경과됐을 때 단 한번 콜백함수를 호출하고 새로운 타이머를 재설정해줍니다.
즉, delay 시간 간격으로 콜백함수가 한번 호출된다고 생각하시면 됩니다.
throttle 이벤트는 특히 무한 스크롤을 구현할때 많이 사용되는 방식입니다.


23장 실행 컨텍스트에서 살펴본 바와 같이
함수는 호출된 순서대로 함수 실행 컨텍스트가 실행 컨텍스트 스택에 푸시됩니다.
그렇기 때문에 함수는 순차적으로 실행되는 것입니다.

위에서 말했다 싶이 JS 엔진은 단 하나의 실행 컨텍스트 스택을 가집니다.
즉, 함수를 실행하는 창구는 단 하나라는 뜻이고 동시에 여러개의 함수를 실행할 수 없다는 뜻입니다.
그렇기에 현재 실행중이지 않은 나머지 함수들은 실행을 대기중인 상태가 됩니다.
이 친구들은 현재 실행중인 컨텍스트가 pop 되어서 제거되면 순차적으로 하나씩 실행됩니다.

이렇게 하나의 함수가 실행되는 동안 나머지 함수들은 실행이 중단되고 대기상태가 되는 것을 블로킹이라고 합니다.
코드

위 코드를 보면 sleep 이란 함수는 호출되면서 3초라는 시간이 지난 후 foo를 호출합니다.
즉, bar는 3초뒤에 foo가 호출될 때 까지 블로킹됩니다.

이러한 처리 방식이 바로 우리가 많이 들어왔던 동기 처리 방식입니다.
동기 처리 방식은 함수의 실행 순서가 보장되지만 앞 태스크가 실행되는 동안 나머지 태스크들이 블로킹 당한다는 단점이 있습니다.
그렇다면 비동기 처리 방식은 무엇일까요?
동기 처리 방식과 정확히 반대입니다.
함수의 실행 순서는 보장되지 않지만 앞 태스크가 실행되는 것을 나머지 태스크들이 기다릴 필요가 없죠.
setTimeout 함수를 사용하여 수정

비동기 처리 방식으로 동작하는 것에는
setTimeout, setInterval, HTTP 요청(네트워크 요청), 이벤트 핸들러가 있습니다.
JS 엔진은 싱글 스레드 동작한다고 했습니다. 한번에 하나의 태스크만 처리할 수 있죠.
그런데 브라우저의 동작을 보면 여러 태스크가 동시에 처리되는 것처럼 보입니다. 🤔
실제로 맞습니다. 이벤트 루프는 자바스크립트의 동시성을 지원합니다.

Google의 V8 JS 엔진을 비롯한 모든 JS 엔진은 크게 2가지 영역으로 나뉩니다.
이처럼 콜스택, 힙은 단순히 태스크가 요청되면 요청된 작업을 순차적으로 처리하는 역할만합니다.
비동기 처리에서 소스코드 평가, 실행을 제외한 모든 영역은 브라우저, 또는 node.js가 담당합니다.
const timerId= setTimeout(()=>console.log(`화이팅!`),300);
setTimeout 콜백함수의 평가, 실행 자체는 JS 엔진에서 해주지만
setTimeout 콜백함수 등록, 실행시간(delay) 설정은 브라우저, 또는 node.js가 한다는 뜻
이렇게 브라우저 환경은 태스크 큐와 이벤트 루프를 제공해줍니다.
태스크 큐: 비동기 함수의 콜백함수, 이벤트 핸들러가 일시적으로 보관되는 영역
이벤트 루프: 콜 스택에 현재 실행중인 컨텍스트 있는지 태스크 큐에 대기중인 비동기 함수가 있는지 지속적으로 확인합니다.
마이크로 태스크 큐: 프로미스의 후속 처리 메서드의 콜백 함수가 일시적으로 보관되는 영역
(45장 참고)

이런 코드가 있을 때, 실행 순서에 대해서 생각해봅시다. 😎
Ajax란 Asynchronous javascript and Xml의 약자로,
이름 그대로 자바스크립트의 비동기 처리 네트워크 요청 방식입니다.
Ajax는 Web API인 XMLHttpRequest 객체를 기반으로 동작합니다.
XMLHttpRequest는 HTTP 비동기 처리를 위한 메서드와 프로퍼티를 제공하죠.
이전의 웹 페이지는 온전한 HTML을 서버로부터 전송 받아서 웹페이지를 매번 처음부터 다시 랜더링 해주는 방식으로 동작했습니다.
따라서 화면이 전환될 때 마다 웹 페이지를 처음부터 다시 렌더링하는 것이죠.
또 클라이언트와 서버의 통신은 동기적으로 처리됐어서 서버로부터 응답이 올 때까지 다음 처리는 블로킹됩니다.

이러한 전통적인 방식은 다음과 같은 단점이 있습니다.
- 변경 사항이 없는 파일도 매번 다시 전송받기 때문에 불필요한 데이터 통신이 발생합니다.
- 변경할 필요가 없는 부분도 다시 렌더링되어 화면 전환이 일어나면 깜박이는 현상이 발생합니다.
- 통신이 동기적으로 이루어지기 때문에 블로킹 현상이 일어납니다.
Ajax가 등장하면서 이러한 전통적인 방식의 단점이 해결될 수 있게 되었습니다.

- 변경할 부분을 갱신하는 데 필요한 데이터만 전송받아 불필요한 데이터 통신이 발생하지 않습니다.
- 변경할 필요가 없는 부분은 다시 렌더링되지 않기 때문에 화면이 깜박이는 현상이 발생하지 않습니다.
- 통신이 비동기적으로 이루어지기 때문에 블로킹이 발생하지 않습니다.
- 즉, 변경 사항이 있는 데이터만 비동기 방식으로 전송받아 불필요한 렌더링이 일어나지 않고 빠른 퍼포먼스와 부드러운 화면 전환이 가능해졌습니다.
JSON(JavaScript Object Notation)은 클라이언트와 서버 간의 HTTP 통신을 위한 문자열 데이터 형식입니다.
자바스크립트에 종속되지 않아 대부분의 프로그래밍 언어에서 사용할 수 있습니다.
JSON은 자바스크립트의 객체 리터럴과 유사하게 키와 값으로 구성된 순수한 텍스트입니다.
JSON의 키와 문자열 값은 반드시 큰따옴표(작은따옴표 x)로 묶어야 합니다.
{
"name": "Lee",
"age": 20,
"alive": true
}
JSON.stringify 메서드는 객체나 배열을 JSON 포맷의 문자열로 변환합니다.
클라이언트가 서버로 객체를 전송하려면 객체를 문자열화해야 하는데 이를 직렬화라고 합니다.
객체 → JSON 변환
const obj = {
"name": "Lee",
"age": 20,
"alive": true
};
const json = JSON.stringify(obj);
console.log( json);
// {"name": "Lee","age": 20,"alive": true}
// 객체를 JSON 포맷의 문자열로 변환하면서 들여쓰기
const prettyJson = JSON.stringify(obj, null, 2);
console.log( prettyJson);
/*
{
"name": "Lee",
"age": 20,
"alive": true
}
*/
JSON.parse 메서드는 JSON 형식의 문자열을 객체나 배열로 변환합니다.
(JSON.stringify의 반대 개념!)
서버로부터 클라이언트에 전송된 JSON 데이터는 문자열입니다.
이 문자열을 객체로서 사용하려면 JSON 포맷의 문자열을 객체화해야 하는데 이를 역직렬화라 합니다.
JSON → 객체 변환
const obj = {
"name": "Lee",
"age": 20,
"alive": true
};
// 객체를 JSON 형식의 문자열로 변환한다.
const json = JSON.stringify(obj);
// JSON 형식의 문자열을 객체로 변환한다.
const parsed = JSON.parse(json);