고차함수를 페어 프로그래밍으로 복습함!
filter
, reduce
, map
등등의 작동 원리를 보기 위해_.each
_.each
는 들어온 Collection에 반복적인 작업을 수행토록 만든다.forEach()
랑 비슷, 반복하게 만드는 순회 함수(iterator)를 만들라는 얘기임_.each = function (collection, iteratee) {
// iterator는 반복하는 애, iteratee 반복 당하는 함수 - 콜백!!
if (Array.isArray(collection)) {
for (let i = 0; i < collection.length; i++) { // 인덱스 순회
iteratee(collection[i], i, collection);
}
} else {
for (let i in collection) { // 키값 순회
iteratee(collection[i], i, collection);
}
}
};
iteratee
를 Collection의 각 요소에 잘 적용시킨 반복문이다. 리턴값도 없음!_.filter
.filter()
를 만들 차례, 만족된 요소만 '리턴'해야한다._.filter = function (arr, test) {
let newArr = [];
_.each(arr, (item) => {
if (test(item)) {
newArr.push(item);
}
});
return newArr;
};
test(item)
_.reduce
어디서부터 누적이 시작되는가
에 대한 답이 없어 파라미터로 initVal이라는 시작 값을 따로 지정iteratee
함수에 이제 acc
라는 누적값도 파라미터로 들어가게끔 입력됨_.reduce = function (arr, iteratee, initVal) {
// 초깃값이 포인트: initVal, 총량: acc, 이전값 : pre
// initVal이 있다면? initVal === acc, initVal이 없다면? acc === arr[0]
let acc = initVal;
_.each(arr, (item, idx, collection) => {
// if (acc === undefined) { // acc를 기준으로 undefined를 해줘 1번째 반복 때 acc가 지정되면 if가 안먹이게 분기를 나눴다! 미쳤다! 더 효율적임
if (initVal === undefined && idx === 0) {
acc = item;
} else {
acc = iteratee(acc, item, idx, collection)
}
});
return acc;
};
_.each
로 적용, 누적값이 있는 지 없는 지 분기를 나눠 acc
재할당_.each
의 iteratee
함수를 써줘 각 요소에 적용 - 누적값(acc)과 수행되지않은 현재 요소(item, ele, pre), 인덱스, collection을 써줌 JS는 기본적으로 동기 처리함, 하지만 브라우저에서 효율적으로 처리하기 위해 비동기 처리로 코드를 짤 때가 있음, 하는 법을 배워보자.
비교 : 카페, 식당, 치킨집, 전화와 문자 등등, 특히 롤에 대한 비유가 있다. 진짜 재밌음 ㅋㅋㅋ
비동기가 좋다는 건 알았지만 비동기 안에서도 동기적으로(순차적으로) 순서를 제어할 경우가 있을 수도 있다. 이 때 콜백으로 제어한다.
const printString = (str) => { setTimeout(() => { console.log(str); }, Math.floor(Math.random() * 100) + 1); }; const printAll = () => { printString("A"); printString("B"); printString("C"); }; printAll(); // ABC, BCA, CAB ... 뒤죽박죽임
A, B, C를 랜덤 시간에 따라찍어내고 싶은 코드 - setTimeout으로 비동기 처리
하지만 시간에 따라 순차적이 아닌 ABC가 랜덤한 순서로 나온다.
여기서 비동기 안 동기 처리를 해 시간을 따라 나오면서 순차적으로 나오게 만들 수 있다!
const printStr = (str, callback) => { setTimeout(() => { console.log(str); callback(); // 추가 }, Math.floor(Math.random() * 100) + 1); }; const printAllCallback = () => { // 콜백 중첩으로 순차적 처리 printString("A", () => { printString("B", () => { printString("C", () => {}); }); }); }; printAllCallback(); // ABC가 순차적으로 랜덤한 시간에 결과가 나옴
콜백을 써줘 동기적으로 처리해 ABC를 안정적으로 도출
근데! 저게 많아지면 '콜백 지옥'이 생김(가독성 꽝, 에러 콜백마다 써줘야함), promise로 해결하자!
callback()
에 파라미터가 없었지만 의도적으로 없는 값 null
을 넣어 조건에 따라 활용할 수 있다.const somethingGonnaHappen = callback => {
waitingUntilSomethingHappens();
if (isSomethingGood) {
callback(null, something); // 실무적으로도 대부분 에러가 앞, 데이터가 뒤로 써줌
}
if (isSomethingBad) {
callback(something, null);
}
}
somethingGonnaHappen((err, data) => {
if (err) {
console.log('ERROR!!');
return;
}
return data;
});
How to deal with 'Callback Chain and Hell'
즉! 콜백을 어떻게 다룰 것이냐에 대한 문법이다!
new Promise()
: 생성자로 만듦resolve()
: go to 'Next Action'reject()
: 'Handle Error'.then()
: Promise
함수를 받을 수 있는(thenable) 것을 받아서 괄호안 콜백을 적용 뒤 리턴promise
는 thenable하지만 thenable은 promise
만 있는 건 아님then
이 파라미터를 받아 콜백 함수에 적어주면 그 전 promise
리턴값에 함수가 적용된 값이 리턴된다!!.then
)을 통해 설정// Promise Constructor(생성자 함수)
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(string);
resolve(); // 실행되는 printAll()만 있기에 reject는 따로 없음
}, Math.floor(Math.random() * 100) + 1);
});
};
// Promise Chaining
const printAll = () => {
printString("A")
.then(() => {
return printString("B");
})
.then(() => {
return printString("C");
});
};
printAll(); // A, B, C
.then()
으로 평평한 구조를 가져 가독성도 좋고 쓰기도 좋다..catch()
로 콜백에 에러가 생길 때 한번만 작성해도 처리 가능!.then
의 return
에 다른 promise를 줘 그 promise의 resolve()
를 이어받아 .then
쓸 수 있음.catch()
를 통해 1. 앱을 죽이지(강제종료) 않고 2. 오류 화면을 띄울 수 있음await
만으로 동기적으로 처리 가능하다!new promise
가 없어도 동기적 처리가 가능하게 만들어준다.new promise
와 async() => {await ~}
는 같이 쓸 수 있다. .then()
대신 await
사용 가능async()
는 .then
과도 쓰고 단독으로 쓰일 수 있지만 await
는 무조건 async()
에 써줘야한다.async function showAvatar() {
// JSON 읽기
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// github 사용자 정보 읽기
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// 아바타 보여주기
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// 3초 대기
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
async()
를 함수에 선언해 단독으로 promise 상태를 만듦.then()
보다 쓰기 쉽고 직관적.then(), .catch()
같이 try{await~}...catch (err) {~err}
로 오류도 잡을 수 있음.then
, .catch
를 써야하기에 기본 구조도 알고 있기API(Application Programming Interface) : 프로그램(앱)과 OS가 상호작용에 사용되는 언어 및 메세지의 정의와 형식 + 걍 추상화 잘된, 나와 프로그램이 상호작용되도록 도와주는 자료형 데이터
효율적으로 쓰기 위해 비동기 처리를 하며 많이 쓰이는 API가 있는데, 그것들을 알아보겠다.
setTimeout(실행콜백, 지연시간(밀리초))
, clearTimeout(setTimerout 함수 이름)
const timer = setTimeout(function () {
console.log('10초 후 실행');
}, 10000);
clearTimeout(timer);
// setTimeout이 종료됨.
setInterval(실행콜백, 지연시간(밀리초)
, clearInterval(setTimerout 함수 이름)
const timer = setInterval(function () {
console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// setInterval이 종료됨.
require
- exports
: ES 전 버전 사용 가능, 파일 어느 지점에서든 호출 가능import
- export
: ES6 이후 사용가능, 무조건 맨위 호출, 사용자가 필요한 모듈만 호출 선택 가능, 성능 우수, 메모리 절약, 요즘 많이// require
const name = require('./module.js');
module.exports = name;
const fs = require('fs');
// import
import name from './module.js';
export default name; // default 내보내기
import fs from 'fs'; // 내장
import { readFile } from 'node:fs'; // 디스트럭쳐링
Promise와 활용 복습함
node.js fs.readFile 함수가 콜백에서 err
를 어떻게 잡느냐가 궁금했다
근데 코치님이 알려주셨다.
readFile의 함수가 끝나면 그 에러인 상황을 판별(파일x 같은)해주는 기준들이 메소드에 내장되어있기 때문에 err
이든 error
든 어떤 이름이든 파라미터로 정해두고 그 에러만 담아주면 된다.
서버와 연동시키는, 네트워크 요청이 가능하게 만들어주는 API
비동기 요청의 가장 큰 예
fetch(url)
// .json으로 파싱하기
.then((response) => response.json())
.then((json) => console.log(json))
// catch로 오류 처리
.catch((error) => console.log(error));
궁금증
fetch를 더 편하게 만들어 줄 수 있는 서드파티 라이브러리다.
.json
도 안해줘도 된다!
진짜 어렵다. 그 자체를 이해하기엔 아직 무리다.
하지만 그 패턴을 이해하고 활용한다면 괜찮을 것이다. 포기하지 말자
코스 졸업 선배가 와서 발표를 했는데 알게 된 것, 유념할 것을 필기 하겠다.