working_helen
[JavaScript 기초] JavaScript 응용 본문
강의명 : 한입 크기로 잘라 먹는 리액트(React.js) - 섹션 2. JavaScript 응용
1. Truthy & Falsy
2. 비 구조화 할당
3. Spread
4. 동기/비동기
5. 콜백 함수
1) 콜백 함수
2) 콜백 지옥 (Callback Hell)
3) Promise
4) async & await
5) API 호출
1. Truthy & Falsy
- Falsy에 해당되는 것 : null, undefined, 0, "" (빈 문자열)
- 단락회로 평가 : 논리연산자가 앞에서부터 평가하고, 결과가 결정되면 뒤를 고려하지 않는 특성
- 아래 코드에서 person이 'Falsy'면 바로 'Falsy'로 name 할당, name이 Truthy면 바로 name 값을 리턴
const getName = (person) => {
const name = person && person.name;
return name || "객체가 아닙니다";
};
// name에 Falsy 할당
// -> false에 해당하는 name은 넘어가고, true에 해당하는 "객체가 아닙니다" 리턴
let p1;
let p2 = undefined;
const name1 = getName(p1);
const name2 = getName(p2);
// name에 Truthy 할당 -> name이 리턴
let p3 = "Mark";
const name3 = getName(p3);
2. 비 구조화 할당
- 배열에서
let arr = ['one', 'two', 'three'];
let [one, two, three] = arr;
[one, two, three] = ['one', 'two', 'three'];
[one, two, three] = ['one', 'two']; //three는 undefined
[one, two, three = 'three'] = ['one', 'two']; //따로 지정
// 비 구조화 할당을 이용한 배열 원소 swap
let a = 10;
let b = 20;
console.log(a, b);
[a,b] = [b,a];
console.log(a, b);
- 객체 정의에서
key 값을 기준으로 할당
let object = {one:'one', two:'two', three:'three'}
let {one, two, three} = object;
// key 값을 기준으로 할당되므로
// 순서에 관계없이 one에는 one이 할당
let {two, three, one} = object;
// one 값을 NewOne이라는 이름의 key에 할당
let {one : NewOne, two, three} = object;
3. Spread
- 객체 혹은 배열에 중복된 원소가 있을 때, 다른 곳에도 동일하게 사용되도록 펼쳐주는 역할
// 모든 쿠키가 동일하게 가지는 원소들
const cookie = {
base : "cookie",
madeIn : "Korea"
};
// 하위 쿠키 객체에 spread
const ChocoCookie = {
...cookie,
topping : "chocolate"
};
const blueberryCookie = {
...cookie,
topping : "blueberry"
};
const fruit = ['apple', 'banana'];
const vegetable = ['carrot', 'potato'];
// fruit와 vegetable 배열 spread + 새로운 원소도 추가
const food = [...fruit, ...vegetable, 'meat'];
4. 동기/비동기
1) 동기 처리 vs 비동기 처리
- 동기 처리 : JS는 코드 작성된 순서에 따라 SingleThread 방식으로 수행, 먼저 시작된 작업을 모두 끝내고 나서야 다음 작업을 수행할 수 있기 때문에 하나의 작업이 너무 오래 걸리면 전체 작업 시간이 길어지는 문제
- 비동기 처리 : SingleThread에 어러 개의 작업을 동시에 실행시켜 수행 시간을 단축하는 방식, 현재 실행중인 작업을 지속하며 다른 작업을 병렬적으로 수행, 작업이 끝나는 시점에 콜백 함수를 호출
setTimeout(()=>{} 수행할 함수, 함수 실행까지 기다릴 시간);
setTimeout((a)=>{console.log(a);}, 1000); // 1000이 1초를 의미
- SetTimeout()과 콜백함수 cb()는 Call Stack이 아닌 Web APIs에 저장
- SetTimeout()의 대기 시간이 종료되면, 콜백함수 cb()가 Callback Queue로 이동
- 콜백함수 cb()는 다시 Call Stackd으로 이동해 함수 실행
2) 비동기 작업의 상태
Pending(대기 상태) → resolve → Fulfilled(성공) 혹은
→ reject → Rejected(실패)
5. 콜백 함수
1) 콜백(Callback) 함수
- 호출하는 함수의 매개변수로 함수 객체 자체를 전달하는 것, 호출 함수 내에서 콜백함수가 실행
- 주로 익명 화살표 함수 형태로 정의하여 사용
- 하나의 콜백함수가 여러 호출 함수에서 사용되는 경우엔 별도로 함수 정의
// 콜백함수를 인자로 전달해서 실행
함수(인자에 콜백함수 cb){
setTimeout(()=>{cb() 실행}, 시간);
}
// 함수 인자로 resolve + reject시 콜백함수 전달
function isPositive(num, resolve, reject) {
setTimeout(()=> {
if(typeof(num) === "number"){
resolve(num >=0 ? "양수" : "음수");
} else {
reject("숫자가 아닙니다");
}
}, 2000);
}
num=5; //num=[];
isPositive(num,
(res) => {console.log("숫자입니다 : ", res);},
(err) => {console.log(err);}
);
2) 콜백 지옥 (Callback Hell)
- 함수의 매개변수로 넘겨지는 콜백 함수가 반복되어 코드의 들여쓰기가 매우 깊어지는 현상
- 비동기 호출이 자주 일어나는 코드에서 발생, 코드의 가독성이 떨어지고 수정하기 어려워진다.
3) Promise
(MDN) 프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다. 다만 최종 결과를 반환하지는 않고, 대신 프로미스를 반환해서 미래의 어떤 시점에 결과를 제공합니다.
- Promise 객체를 return 하는 방식으로 콜백 지옥을 탈출할 수 있다.
- 비동기 처리의 결과를 객체에 저장해서 활용할 수 있게 해준다.
- Promise를 반환하는 함수 = 비동기 처리되는 함수
- Promise 객체에 then/catch method를 적용해 콜백함수 수행
- Promise.then : resolve를 실행했을때 결과값을 파라미터로 받아서 콜백함수 수행
- Promise.catch : reject를 실행했을때 결과값을 파라미터로 받아서 콜백함수 수행
function isPositiveP(num){
// resolve, reject 콜백 함수를 받아서 수행할 내용
const executor = (resolve, reject) => {
setTimeout(()=> {
if(typeof(num) === "number"){
resolve(num >=0 ? "양수" : "음수");
} else {
reject("숫자가 아닙니다");
}
}, 2000);
};
// 위의 결과값을 Promise 객체로 리턴
const asyncTask = new Promise(executor);
return asyncTask;
}
const res = isPositiveP([]);
res
.then((res) => {
console.log("숫자입니다 : ", res); // resolve 콜백함수 수행
})
.catch((err) => {
console.log(err); // reject 콜백함수 수행
});
- Promise로 콜백 함수 코드 개선하기
function taskA(a, b, cb){
setTimeout(()=>{
const res = a+b;
cb(res);
}, 1000);
}
function taskB(a, cb){
setTimeout(()=>{
const res = a*2;
cb(res);
}, 2000);
}
function taskC(a, cb){
setTimeout(()=>{
const res = a*(-1);
cb(res);
}, 1000);
}
taskA(3, 4, (a_res)=>{
console.log("taskA : ", a_res); // taskA의 콜백함수
taskB(a_res, (b_res)=>{
console.log("taskB: ", b_res); //taskB의 콜백함수
taskC(b_res, (c_res)=>{
console.log("taskC: ", c_res); //taskC의 콜백함수
})
})
});
▼
// cb()를 따로 받지 않고, 바로 resolve나 reject 실행
function taskA(a, b){
const executor = (resolve, reject) =>{
setTimeout(()=>{
const res = a+b;
resolve(res);
}, 1000);
};
const asyncTask = new Promise(executor);
return asyncTask;
}
// executor 객체 생성 과정을 Promise에 바로 입력
function taskB(a){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
const res = a*2;
resolve(res);
}, 2000);
});
}
function taskC(a){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
const res = a*(-1);
resolve(res);
}, 1000);
});
}
taskA(5, 1).then((a_res)=>{
console.log("taskA: ", a_res);
return taskB(a_res); // 콜백함수를 실행, Promise 객체를 리턴
}).then((b_res)=>{ // 리턴된 Promise 객체를 바로 이어서 이용
console.log("taskB: ", b_res);
return taskC(b_res);
}).then((c_res)=>{
console.log("taskC: ", c_res);
})
※ Promise Hell
: 지나친 then method 남용으로 코드가 길어지는 것
Promise를 이용한 비동기 처리의 가독성을 높이기 위해 async & await 활용
4) async & await
① async
- Promise를 리턴하는 비동기 처리 함수로 지정, 리턴값이 Promise 객체
- 내부에 await 함수를 사용할 수 있게 처리한다.
② await
- 비동기 함수 앞에 붙여 비동기 함수가 동기 함수처럼 작동하게 만듬
- 비동기 함수에 await를 붙히면 함수의 수행이 완료되기 전까지 다음 코드를 실행하지 않는다.
- async가 붙은 함수 내에서만 사용될 수 있다.
(예제 1)
- 비동기 처리 함수 hello()는 Promise 객체를 리턴
- await hello()는 Promise 객체의 resolve() method 실행 결과를 리턴
async function hello() {
return "hello Async";
}
// Promise 객체 리턴
console.log(hello()); //A
// Promise 객체에 콜백함수 수행
hello().then((res)=>{
console.log(res); //B
});
// asymc 함수 내에서 awiat로 실행
async function main() {
const result = hello(); //C
console.log(result);
const result2 = await hello();
console.log(result2); //D
}
main();
(예제 2)
// Promise 객체 반환 비동기 함수
function delay(ms) {
return new Promise(resolve => {
console.log(`${ms}초 시작`);
setTimeout(() => {
console.log(`${ms}초 종료`);
resolve()
}, ms);
});
}
async function main() {
delay(1000); //A
delay(2000); //B
const result = Promise.resolve(); //C
console.log(result);
}
main();
- 비동기 처리되는 A, B, C 코드 순서대로 실행
- 그로 인해 1초와 2초가 다 지나기 전에 C 함수 실행됨
async function main() {
await delay(1000); //A
await delay(2000); //B
const result = Promise.resolve(); //C
console.log(result);
}
main();
- A와 B가 동기 처리 되었기 때문에 1초, 2초가 다 지난 후에 다음 함수 실행
async function main() {
delay(1000); //A
await delay(2000); //B
const result = await Promise.resolve("종료"); //C
console.log(result);
}
main();
- A는 비동기 함수이므로 1초가 다 지나기 전에 B 실행
- B는 동기 처리되었으므로 B가 다 끝난 다음에 C 실행
- await Promise.resolve() : Promise 객체를 resolve에 수행한 결과로 리턴
5) API 호출
- API의 개념 : 2023.07.04 - [TAVE/뿌스팅 프로젝트] - [데이터 수집] API의 개념 / XML 형태 처리
- API에 접근해서 데이터를 얻고, json 형태로 변환하는 비동기 처리 함수 정의
async function getData(){
let rwaResponse = await fetch("API 주소");
let jsonResponse = await rwaResponse.json();
}
getData();
Reference
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%BD%9C%EB%B0%B1-%ED%95%A8%EC%88%98
https://velog.io/@seul06/JavaScript-%EC%BD%9C%EB%B0%B1-%EC%A7%80%EC%98%A5
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B9%84%EB%8F%99%EA%B8%B0%EC%B2%98%EB%A6%AC-async-await
'외부 수업 > React 스터디' 카테고리의 다른 글
[React 기초] State / Props (0) | 2024.01.15 |
---|---|
[React 기초] Node.js와 React.js 기본개념 (0) | 2024.01.15 |
[JavaScript 기초] 객체 / 배열 (1) | 2024.01.14 |
[JavaScript 기초] 자료형 / 함수 선언 (0) | 2024.01.13 |
[HTML] 기본 태그 / 회원가입 폼 실습 (1) | 2024.01.13 |