자바스크립트는 싱글 쓰레드(Single Thread)로 동작하는 언어입니다.
(일꾼이 한명이라서 한번에 하나의 작업만 할 수 있다. , 메인 쓰레드 하나, 콜스택 하나로 구성되어 있다.)
그리고 비동기 작업을 동시에 할 수 있습니다.
1번에 1개의 작업만 할 수 있다고 했는 데 어떻게 동시 실행을 하나요??
-> 자바스크립트는 코어 엔진만 가지고 돌아가지 않습니다. 실행 환경(런타임)의 도움을 받아 동시 실행을 할 수 있습니다. (Web API(DOM, Ajax, setTimeout), Task Queue, Event Loop 등과 함께 동작합니다.)
- 콜백이란?
: 자바스크립트가 비동기 처리를 하기 위한 패턴 중 하나입니다. (콜백 함수란? 함수에 인자로 함수를 넣는 것을 말한다.)
전통적인 콜백 패턴은 일명 콜백 헬이라고 불리는 엄청난 중첩 문제가 생기기 쉽습니다.
1) 콜백 헬
: 꼬리에 꼬리를 무는 비동기 처리가 늘어나면 호출이 계속 중첩되고, 코드가 깊어지고, 관리가 어려워 지는 데
이런 깊은 중첩을 콜백 헬이나 멸망의 피라미드라고 부릅니다.
function async1('a', function (err, async2){
if(err){
errHandler(err);
}else{
...
async2('b', function (err, async3){
...
}){
...
}
}
});
-> 이런 콜백 헬이 발생하는 이유는??
- 비동기 처리 시에는 실행 완료를 기다리지 않고 바로 다음 작업을 실행합니다.
- 즉, 순서대로 코드를 쭉 적는다고 우리가 원하는 순서로 작업이 이뤄지지 않습니다.
- 비동기 처리 함수 내에서 처리 결과를 반환하는 걸로는 원하는 동작은 하지 않기 때문에, 콜백 함수를 사용해서 원하는 동작을 하게 하려고 콜백 함수를 사용합니다.
- 이 콜백 함수 내에서 또 다른 비동기 작업이 필요한 경우 위와 같은 중첩이 생기면서 콜백 헬이 탄생합니다.
- 프라미스란?
: 비동기 연산이 종료된 이후에 결과를 알기 위해 사용하는 객체입니다.
프라미스를 사용하면 비동기 메소드를 마치 동기 메소드처럼 값을 반환 할 수 있습니다.
전통적인 콜백 패턴으로 인한 콜백 헬 때문에 ES6에서 도입한 또다른 비동기 처리 패턴입니다.
비동기 처리 시점을 좀 더 명확하게 표현 할 수 있습니다.
- 프라미스는 Promise 생성자 함수(new 키워드)를 사용하여 생성 합니다.
- 비동기 작업을 수행 할 콜백 함수를 인자로 전달 받아서 사용합니다.
// 프라미스 객체를 만듭니다.
// 인자로는 (resolve, reject) => {} 이런 excutor 실행자(혹은 실행 함수라고 불러요.)를 받아요.
// 이 실행자는 비동기 작업이 끝나면 바로 두 가지 콜백 중 하나를 실행합니다.
// resolve: 작업이 성공한 경우 호출할 콜백
// reject: 작업이 실패한 경우 호출할 콜백
const promise = new Promise((resolve, reject) => {
if(...){
...
resolve("성공!");
}else{
...
reject("실패!");
}
});
1) 프라미스의 상태값
- pending: 비동기 처리 수행 전(resolve, reject가 아직 호출되지 않음)
- fulfilled: 수행 성공(resolve가 호출된 상태)
- rejected: 수행 실패(reject가 호출된 상태)
- settled: 성공 or 실패(resolve나 reject가 호출된 상태)
2) 프라미스 후속 처리 메소드
- 프라미스로 구현된 비동기 함수는 프라미스 객체를 반환합니다.
- 프라미스로 구현된 비동기 함수를 호출하는 측에서는 이 프라미스 객체의 후속 처리 메서드를 통해 비동기 처리 결과(성공 결과나 에러메시지)를 받아서 처리해야 합니다.
- .then(성공 시, 실패 시)
then의 첫 인자는 성공 시 실행, 두번째 인자는 실패 시 실행됩니다. (첫 번째 인자만 넘겨도 됩니다!)
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000);
});
// resolve
promise.then(result => {
console.log(result); // 완료!가 콘솔에 찍힐거예요.
}, error => {
console.log(error); // 실행되지 않습니다.
});
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("오류!")), 1000);
});
// reject
promise.then(result => {
console.log(result); // 실행되지 않습니다.
}, error => {
console.log(error); // Error: 오류!가 찍힐거예요.
});
- .catch(실패 시)
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("오류!"), 1000);
});
promise.catch((error) => {console.log(error};);
- promise chaining (프라미스 체이닝)
: 프라미스는 후속 처리 메소드를 체이닝 해서 여러 개의 프라미스를 연결 할 수 있습니다.
(이 방법을 사용해서 콜백 헬을 해결 할 수 있습니다)
1) 체이닝은 무엇이고, 어떻게 사용 할까요??
: 후속 처리 메소드 (then)을 쭉쭉 이어 주면 됩니다.
new Promise((resolve, reject) => {
setTimeout(() => resolve("promise 1"), 1000);
}).then((result) => { // 후속 처리 메서드 하나를 쓰고,
console.log(result); // promise 1
return "promise 2";
}).then((result) => { // 이렇게 연달아 then을 써서 이어주는 거예요.
console.log(result);
return "promise 3";
}).then(...);
- async, await
: 프라미스 사용을 엄청 편하게 만들어 주는 키워드입니다.
[더 알면 좋은 내용]
강의에서 다루지 않지만 제네레이터라는 함수와 이터러블을 알면 더더 좋습니다.
1) async
- 함수 앞에 async를 붙여서 사용합니다.
- 항상 프라미스를 반환합니다.
(프라미스가 아닌 값이라도, 프라미스로 감싸서 반환 해줍니다.)
// async는 function 앞에 써줍니다.
async function myFunc() {
return "프라미스를 반환해요!"; // 프라미스가 아닌 걸 반환해볼게요!
}
myFunc().then(result => {console.log(result)}); // 콘솔로 확인해봅시다!
2) await
- async의 짝꿍입니다. (async 없이는 사용하지 못합니다.)
- async 함수 안에서만 동작합니다.
- await는 프라미스가 처리 될 때까지 기다렸다가 그 이후에 결과를 반환합니다.
(다른 작업을 하지 않고 프라미스에서 값이 돌아 올 때까지 기다립니다.
async function myFunc(){
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000);
});
console.log(promise);
let result = await promise; // 여기서 기다리자!하고 신호를 줍니다.
console.log(promise);
console.log(result); // then(후처리 함수)를 쓰지 않았는데도, 1초 후에 완료!가 콘솔에 찍힐거예요.
}
'항해 중 > 5주차 리액트 심화반' 카테고리의 다른 글
2주차 - 웹 저장소(feat. 토큰) (0) | 2021.11.30 |
---|---|
2주차 - 토큰 기반 인증(OAuth 2.0, JWT) (0) | 2021.11.30 |
1주차 - 프로젝트 생성, 최소 단위 컴포넌트 만들기, 숙제 (0) | 2021.11.29 |
1주차 - JavaScript Re-Start, Prototype (0) | 2021.11.29 |
5주차 개인 과제 (0) | 2021.11.29 |
댓글