[마스터 개념] 7 | 프로미스
1 variable 변수
2 operator 연산자
3 function 함수
4 object 객체
5 class 클래스
7 built-in 빌트인 객체
8 array 배열
9 iterator 이터러블
10 map
11 more-operators 유용한 연산자들
12 module 모듈
13> promise 프로미스
14 scope 스코프
15 prototype 프로토타입
16 closure 클로져
17 this
13 promise 프로미스
callstack
자바스크립트는 동기적으로 수행된다. 따라서 무겁고 오래 걸리는 작업을 수행하기에는 적합하지 않다.
동기적 : 직렬, 작업이 종료될 때까지 기다린 후 다음 작업을 수행하는 방식
비동기적 : 병렬, 다른 작업을 하고 있다가, 요청했던 작업이 종료되면 추가 작업을 수행하는 방식
비동기적으로 수행하려면,
1. JavaScript Runtime Environment 에서 비동기적으로 처리하는 API 를 사용하여 원하는 callback 함수를 비동기적으로 작업
2. 그 작업을 마치면 그 callback 함수를 task queue 에 넣음
3. call stack 과 task queue 를 감시하는 event loop 가 call stack 이 비어있는 경우에 task queue 에 있는 callback 함수를 call stack 로 가져옴
function execute() {
console.log("1");
setTimeout(() => {
console.log("2");
}, 3000);
console.log("3");
}
execute(); // 1
// 3
// 2
setTimeout( ) : 콜백함수를 지정된 시간(밀리초) 후에 실행하는 비동기 함수
1. execute( ) 실행
2. 1 출력
3. setTimeout( ) 비동기 함수 실행 -> 해당 콜백함수 비동기로 실행
4. 콜백함수는 비동기로 작업하고 있고, 다음 작업인 3 출력 -> call stack 비어있음
5. 콜백함수 작업 끝나면 task queue 에 넣고, call stack 이 비어있으니 콜백함수 call stack 에 가져와서 2 출력
Promise 프로미스
비동기적으로 처리할 수 있도록 도와주는 Promise 객체가 있다.
function runInDelay(seconds) {
return new Promise((resolve, reject) => {
if (!seconds || seconds < 0) {
reject(new Error("seconds 가 없거나 0보다 작음"));
}
setTimeout(resolve, seconds * 1000);
});
}
runInDelay(2)
.then(() => console.log("타이머 완료!!"))
.catch(console.error)
.finally(() => console.log("끝났다"));
runInDelay( ) 함수는 setTimeout( ) 함수에서의 밀리초를 초로 바꾼 함수이다.
최종적으로 프로미스로 만든 runInDelay( ) 를 호출하면
.then(성공하면 호출됨. 필요한 일을 수행)
.catch(실패하면 호출됨. 에러를 잡음)
.finally(성공 and 실패 시 호출됨. 최종적으로 수행)
runInDelay( )를 프로미스로 만들려면 new Promise( ) 객체를 반환해야 하는데, 이 프로미스 객체 안에서는 비동기적으로 처리된다.
새로운 프로미스 객체는
성공할 때, then 을 호출할 때 실행할 reslove( ) 와
실패할 때, catch 를 호출할 reject( ) 이렇게 2개의 인자를 갖는다.
이때, reject( ) 에는 new Error( ) 처럼 새로운 에러를 만들어 줘야 한다.
// 1초 뒤 바나나
function getBanana() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("바나나");
}, 1000);
});
}
// 3초 뒤 사과
function getApple() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("사과");
}, 3000);
});
}
// 오렌지는 없음. error 발생
function getOrange() {
return Promise.reject(new Error("no orange"));
}
// 바나나와 사과 같이 가져오기
getBanana()
.then((banana) =>
getApple()
.then((apple) => [banana, apple])
)
.then(console.log); // [ '바나나', '사과' ] 4초 뒤
getBanana( ) 는 Promise 지만 바나나를 가져온 다음, 사과를 가져와 동기적으로 처리된다. 따라서 총 1초 + 3초 = 4초가 소요된다.
Promise.all([getBanana(), getApple()])
.then((fruits) => console.log("all", fruits)); // all [ '바나나', '사과' ] 3초 뒤
Promise.all([getBanana(), getApple(), getOrange()])
.then((fruits) => console.log("all-error", fruits))
.catch(console.log); // X
Promise.allSettled([getBanana(), getApple(), getOrange()])
.then((fruits) => console.log("all-settle", fruits))
.catch(console.log);
// all-settle [
// { status: 'fulfilled', value: '바나나' },
// { status: 'fulfilled', value: '사과' },
// {
// status: 'rejected',
// reason: Error: no orange
// at getOrange (C:\Users\...)
// at Object.<anonymous> (C:\Users\...)
// at Module._compile (node:internal/modules/cjs/loader:1105:14)
// at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
// at Module.load (node:internal/modules/cjs/loader:981:32)
// at Function.Module._load (node:internal/modules/cjs/loader:822:12)
// at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
// at node:internal/main/run_main_module:17:47
// }
// ]
Promise.all 은 병렬적으로 한 번에 모든 Promise 들을 실행한다. 따라서 총 1초, 3초 = 3초가 소요된다.
하지만 error 를 발생시키는 getOrange( ) 가 있어서 catch 를 해줘도 then 이 실행되지 않으므로 "all-error" 는 출력되지 않는다. 따라서 성공한 것만 가져올 수 있다.
Promise.allSettled 는 주어진 Promise 의 결과를 모두 받아볼 수 있다.
Promise.race([getBanana(), getApple()])
.then((fruits) => console.log("race", fruits)); // race 바나나
Promise.race 는 주어진 Promise 중 제일 빨리 수행된 것이 이기며 빠른 것만 가져온다. 따라서 1초 < 3초 = 1초가 소요된다.
async await
// 바나나와 사과 같이 가져오기
getBanana()
.then((banana) =>
getApple()
.then((apple) => [banana, apple])
)
.then(console.log); // [ '바나나', '사과' ]
중첩된 콜백함수는 지저분하고 가독성이 떨어진다.
// 바나나와 사과 같이 가져오기
async function fetchFruits() {
const banana = await getBanana();
const apple = await getApple();
return [banana, apple];
}
fetchFruits()
.then((fruits) => console.log(fruits)); // [ '바나나', '사과 ]
따라서 비동기 함수 앞에 'async' 키워드를 붙이면 함수 내부에서 동기적으로 처리할 수 있다.
Promise 를 반환하는 함수를 호출할 때는 await 를 사용하여 비동기적으로 처리하는데, resolve 되면 그 값을 변수에 할당한다.
그냥 반환값만 있을 때는 반환값을 reslove 하는 Promise 가 만들어진다.
JSON
Json (JavaScript Object Notation) : 서버와 클라이언트(브라우저, 모바일) 간의 HTTP 통신을 위한 오브젝트 형태의 텍스트 포맷
stringify(object) -> JSON : 직렬화 Serializing, 객체를 문자열로 변환, 데이터만 포함, 함수 포함 X
parse(JSON) -> object : 역직렬화 Deserializing, 문자열 데이터를 자바스크립트 객체로 변환
'💠프로그래밍 언어 > JavaScript' 카테고리의 다른 글
[마스터 개념] 9 | 클로져, this (0) | 2022.11.15 |
---|---|
[마스터 개념] 8 | 스코프, 프로토타입 (0) | 2022.11.15 |
[마스터 개념] 6 | 모듈 (0) | 2022.11.07 |
[마스터 개념] 5 | map, 유용한 연산자들 (0) | 2022.11.01 |
[마스터 개념] 4 | 이터러블 (0) | 2022.11.01 |