728x90
📍 17일 차 11.17. 수.(온라인 강의)
오늘은 어제 배웠던 동기 / 비동기
, 콜백함수
, promise
에 대해 더 자세하게 배웠다. promise
는 3~4개월 전인가? 토스 코딩 테스트에서 비동기적으로 api
호출하는 테스트가 나왔었는데, 그때 문제의 의도를 정확하게 파악하지 못해서 틀렸던 경험이 있었다. 프론트엔드와 비동기는 떼려야 뗄 수 없는 관계이므로 잘 기억하자.
❏ 자바스크립트 제어 흐름
- 자바스크립트는 다른 멀티스레드 프로그래밍 언어
(JAVA, C++)
와 다른 방식으로 비동기 동작을 처리한다. - 처음 자바스크립트를 접하는 경우, 동작에 대한 정확한 이해가 없으면 코드의 흐름을 따라가기 어렵다.
- 자바스크립트 내부의 비동기 동작을 이해하기 위해서는 이벤트 루프 등의 개념을 알아야만 한다.
- JS 엔진은 하나의 메인 스레드로 구성된다.
- 메인 스레드는 코드를 읽어 한 줄 씩 실행한다.
- 브라우저 환경에서는 유저 이벤트를 처리하고 화면을 그린다.
❏ 동기적 제어 흐름
- 동기적 제어 흐름은 현재 실행중인 코드가 종료되기 전까지 다음 라인의 코드를 실행하지 않는 것을 의미한다.
- 분기문, 반복문, 함수 호출은 동기적으로 실행된다.
- 코드의 흐름과 실제 제어 흐름이 동일하다.
- 싱글 스레드 환경에서 메인 스레드를 긴 시간 점유하면, 프로그램을 멈추게 한다.
❏ 비동기적 제어 흐름
- 비동기적 제어 흐름은 현재 실행중인 코드가 종료되기 전에 다음 라인의 코드를 실행하는 것을 의미한다.
- 프로미스 ,콜백 함수 등은 비동기적으로 실행된다.
- 코드 흐름과 실제 제어 흐름이 다르다.
- 비동기 작업을 기다리는 동안 메인 스레드는 다른 작업을 처리한다.
❏ 이벤트 루프
- JS 엔진은 비동기 처리를 제공하지 않는다.
- 대신, 비동기 코드는 정해진 API(
setTimeout
,XMLHttpRequest
,fetch
)를 제공하여 활용할 수 있다. node.js
의 경우 파일 처리 API, 암호화 API 등을 제공한다.
// 타이머 비동기 처리
setTimeout(() => console.log("타이머 끝"), 1000);
setInterval(() => console.log("인터벌 타이머"), 1000);
// 네트워크 처리
fetch("https://google.com")
.then(() => console.log("네트워크 요청 성공"))
.catch(() => console.log("네트워크 요청 실패"))
- 비동기 코드를 처리하는 모듈은 JS 엔진 외부에 있다.
event queue
,task queue
,job queue
등으로 구성된다.- API 모듈은 비동기 요청을 처리 후 태스크 큐에 콜백 함수를 넣는다.
- JS 엔진은 콜 스택이 비워지면,
event Loop
에서task queue
의 콜백 함수를call stack
으로push
한다. call stack
에 있는 콜백 함수가 실행된다.
// 비동기 처리가 끝나면 콜백 함수를 task queue로 밀어 넣는다.
request("user-data", (userData) => {
console.log("userData 로드")
saveUsers(userData)
})
console.log("DOM 변경");
console.log("유저 변경");
728x90
❏ Promise
- 비동기 API 중 하나이다.
- 태스크 큐가 아닌 잡 큐(
Job queue
혹은Microtask queue
)를 사용한다. - 잡 큐는 태스크 큐보다 우선순위가 높다.
setTimeout(() => {
console.log("타임아웃1")
}, 0);
Promise.resolve().then(() => console.log("프로미스 1"));
setTimeout(() => {
console.log("타임아웃2")
}, 0);
Promise.resolve().then(() => console.log("프로미스 2"));
👉🏽 프로미스 1 프로미스 2 타임아웃1 타임아웃2
- 비동기 작업을 표현하는 자바스크립트 객체
- 비동기 작업의 진행, 성공, 실패 상태를 표현한다.(new Promise(resolve, reject), fetch(promise 반환))
- 비동기 처리의 순서를 표현할 수 있다.
then
,catch
,finally
,then(cb1, bc2)
로cb1
자리에 성공,cb2
자리에 실패 메서드를 인자로 넘길 수 있다.promise method chain
:then / catch
메서드가 또 다른promise
를 리턴하여, 비동기 코드에 순서를 부여한다. 동일한 객체에 메서드를 연결할 수 있는 것을 체이닝이라고 한다. 함수를 호출한 주체가 함수를 끝낸 뒤 자기 자신을 리턴하도록 하여 구현한다. (함수의 끝에return this
가 생략되어있기 때문에 가능하다.), 비동기 코드의 순서를 쉽게 부여 가능하다.
promise
.then((data) => {
return fetchUser(data);
})
.then((user) => {
console.log("user : ", user);
})
.catch((e) => {
console.log("실패 : ", e);
});
Promise.resolve(10).then(console.log)
: 성공한Promise
를 바로 반환한다. 인위적으로Promise
메서드 체인을 만들 수 있다. 비동기 코드로 진행해야 하는 상황 등에 유용하게 사용할 수 있다.Promise.reject("Error").then(console.log)
: 실패한Promise
를 바로 반환한다.
Promise.resolve(10).then(() => console.log("성공"))
👉🏽 성공
Promise.reject(new Error("에러!")).then(() => console.log("실패"))
👉🏽 (node:24270) UnhandledPromiseRejectionWarning: Error: 에러!
promise.all
: 모든promise
가settled
될 때까지 기다린다. 만약,promise
의 배열을 받아 모두 성공하면 각promise
의resolved
값을 배열로 반환한다. 하나의promise
라도 실패하면 가장 먼저 실패한promise
의 실패 이유를 반환한다.
Promise.all([
promise1,
promise2,
promise3,
])
.then((values) => {
console.log("모두 성공", values)
})
.catch((e) => {
console.log("하나라도 실패", values)
})
- promise를 리턴하는 값이 같으면
then
을 생략할 수 있다
// 2개의 API에 모두 then을 사용한 방식
promise
.then((item) => getUserNameById(item.id))
.then((id) => id)
.catch(e => e.message);
// 2개의 API 중 한개만 then을 사용한 방식
promise
.then((item) => getUserNameById(item.id))
.catch(e => e.message);
반응형
'Frontend > 엘리스 SW 엔지니어 트랙' 카테고리의 다른 글
[ 엘리스 SW 엔지니어 트랙 ] 19일차 (0) | 2021.11.19 |
---|---|
[ 엘리스 SW 엔지니어 트랙 ] 18일차 (0) | 2021.11.18 |
[ 엘리스 SW 엔지니어 트랙 ] 16일차(4주차: 자바스크립트 III - Promise, async / await, API 통신) (0) | 2021.11.16 |
[ 엘리스 SW 엔지니어 트랙 ] 15일차 (0) | 2021.11.15 |
[ 엘리스 SW 엔지니어 트랙 ] 14일차 (0) | 2021.11.12 |
댓글