자바스크립트 엔진은 싱글 스레드 방식으로 처리
현대 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식을 동기처리라고 함
현재 실행중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하는 방식을 비동기 처리라고 함
이벤트 루프는 자바스크립트의 동시성을 지원함
태스크 큐
자바스크립트를 사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 웹페이지를 동적으로 갱신하는 프로그래밍 방식
키와 값으로 구성된 텍스트
키는 큰따옴표로 묶어야 한다
값은 객체 리터럴과 같은 표기법을 사용
문자열은 반드시 큰따옴표로 묶어야 한다
객체를 JSON 포맷의 문자열로 변환
직렬화: 객체를 문자열화 하는 것
JSON 포맷의 문자열을 객체로 변환
역직렬화: 문자열을 객체화 하는 것
브라우저에서 제공하는 Web API이므로 브라우저 환경에서만 정상적으로 실행
// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();
// HTTP 요청 초기화
xhr.open('GET', '/users');
// HTTP 요청 헤더 설정
// 클라이언트가 서버로 전송할 데이터의 MIME 타입 지정: json
xhr.setRequestHeader('content-type', 'application/json');
// HTTP 요청 전송
xhr.send();
콜백 함수를 통해 비동기 처리 결과에 대한 후속 처리를 수행하면서 콜백 함수 호출이 중첩되어 복잡도가 높아지는 현상
에러는 호출자(caller)방향으로 전파된다
Promise 생성자 함수는 비동기 처리를 할때 콜백함수를 인수로 전달 받는데 콜백함수는 resolve와 reject를 함수를 인수로 전달 받는다
// 프로미스 생성
const promise = new Promise((resolve, reject) => {
// Promise 함수의 콜백 함수 내부에서 비동기 처리를 수행한다.
if (/* 비동기 처리 성공 */) {
resolve('result');
} else { /* 비동기 처리 실패 */
reject('failure reason');
}
});
프로미스의 비동기 처리 상태가 변화하면 후속 처리 메서드에 인수로 전달한 콜백 함수가 선택적으로 호출
첫 번째 콜백 함수는 비동기 처리가 성공 했을때 호출
두 번째 콜백 함수는 비동기 처리가 실패 했을때 호출
// fulfilled
new Promise(resolve => resolve('fulfilled'))
.then(v => console.log(v), e => console.error(e)); // fulfilled
// rejected
new Promise((_, reject) => reject(new Error('rejected')))
.then(v => console.log(v), e => console.error(e)); // Error: rejected
한 개의 콜백 함수를 인수로 전달 받음
프로미스가 rejected상태인 경우만 호출
catch메서드는 then과 동일하게 동작 언제나 프로미스를 반환
// rejected
new Promise((_, reject) => reject(new Error('rejected')))
.catch(e => console.log(e)); // Error: rejected
프로미스의 성공 또는 실패와 상관없이 무조건 한 번 호출
then/catch메서드와 마찬가지로 언제나 프로미스를 반환
new Promise(() => {})
.finally(() => console.log('finally')); // finally
에러처리는 then메서드에서 보단 catch메서드에서 하는것을 권장
then메서드를 호출한 이후에 호출하면 비동기 처리에서 발생한 에러뿐만 아니라 then메서드 내부에서 발생한 에러까지 모두 캐치 가능
promiseGet('https://jsonplaceholder.typicode.com/todos/1')
.then(res => console.xxx(res))
.catch(err => console.error(err)); // TypeError: console.xxx is not a function
const url = 'https://jsonplaceholder.typicode.com';
// id가 1인 post의 userId를 취득
promiseGet(`${url}/posts/1`)
// 취득한 post의 userId로 user 정보를 취득
.then(({ userId }) => promiseGet(`${url}/users/${userId}`))
.then(userInfo => console.log(userInfo))
.catch(err => console.error(err));
then->then->catch 순서로 후속 처리 메서드를 호출
이미 존재하는 값을 래핑하여 프로미스를 생성하기 위해 사용
Promise.resolve는 인수로 전달 받은 값을 resolve하는 프로미스를 생성
// 배열을 resolve하는 프로미스를 생성
const resolvedPromise = Promise.resolve([1, 2, 3]);
resolvedPromise.then(console.log); // [1, 2, 3]
Promise.reject 메서드는 인수로 전달받은 값을 reject하는 프로미스를 생성
// 에러 객체를 reject하는 프로미스를 생성
const rejectedPromise = Promise.reject(new Error('Error!'));
rejectedPromise.catch(console.log); // Error: Error!
여러개의 비동기 처리를 모두 병렬 처리 할 때 사용
const requestData1 = () => new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () => new Promise(resolve => setTimeout(() => resolve(3), 1000));
Promise.all([requestData1(), requestData2(), requestData3()])
.then(console.log) // [ 1, 2, 3 ] ⇒ 약 3초 소요
.catch(console.error);
모든 프로미스가 fulfilled 상태가 되는것을 기다리는 것이 아니라 가장 먼저 fulfilled상태가 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스를 반환
Promise.race([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
])
.then(console.log) // 3
.catch(console.log);
전달된 프로미스가 하나라도 rejected상태가 되면 에러를 reject하는 새로운 프로미스를 즉시 반환
Promise.race([
new Promise((_, reject) => setTimeout(() => reject(new Error('Error 1')), 3000)),
new Promise((_, reject) => setTimeout(() => reject(new Error('Error 2')), 2000)),
new Promise((_, reject) => setTimeout(() => reject(new Error('Error 3')), 1000))
])
.then(console.log)
.catch(console.log); // Error: Error 3
프로미스 요소로 갖는 배열 등의 이터러블을 인수로 전달 받는다. 전달받은 프로미스가 모두 settled 상태가 되면 처리 결과를 배열로 반환
마이크로태스크 큐는 태스크큐보다 우선순위가 높다
setTimeout(() => console.log(1), 0);
Promise.resolve()
.then(() => console.log(2))
.then(() => console.log(3));
2->3->1 순으로 출력
프로미스의 후속처리 메서드의 콜백함수는 마이크로태스크큐에 저장되기 때문
fetch함수는 HTTP응답을 나타내는 Response 객체를 래핑한 Promise객체를 반환
fetch 함수가 반환하는 프로미스는 기본적으로 HTTP에러가 발생해도 에러를 reject하지 않고 불리언 타입의 ok상태를 false로 설정한 Response객체를 reject한다.
네트워크 장애나 CORS에러에 의해 요청이 완료되지 못한 경우에만 프로미스를 reject한다